我正在研究一种实验方法,该方法将使用bean名称,属性名称和值表达式,并使用Spring SPeL为该bean的属性分配该值。使用此方法的类是ManagedResource,因此我可以从JMX到达它。
然后,我定义了另一个简单的类,为其提供了一个属性和一个Component批注。我还将这个类自动连接到jmx bean类中,只是为了验证该类型的bean是否存在。
然后,我启动了SpringBoot服务。
然后,我从VisualVM调用了该方法。
它失败了,说找不到该名称的bean。
因此,现在更详细。
这是头等舱:
@Component
@ManagedResource
public class JMXDemonstration {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private SomeRandomThing thing;
@Value("${jmxDemonstration.name}")
private String name;
@ManagedAttribute
public String getName() { return name; }
@ManagedAttribute
public void setName(String name) { this.name = name; }
@ManagedOperation
public String buildHelloWorldMessage() {
return "Hello, " + name + ": " + thing.getId();
}
@ManagedOperation
public void assignValueToBeanProperty(String beanName, String propertyName, String expression) {
Object bean = applicationContext.getBean(beanName);
ExpressionParser parser = new SpelExpressionParser();
SimpleEvaluationContext evalContext = SimpleEvaluationContext.forReadWriteDataBinding().build();
parser.parseExpression(propertyName).setValue(evalContext, bean, expression);
}
}
这是另一类:
@Component
public class SomeRandomThing {
private String id;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
}
当我从VisualVM调用该方法时,我传递了“ SomeRandomThing”,“ id”和“ xxx”。
失败的原因是:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'SomeRandomThing' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:685)
我还在该方法中设置了一个断点,并查看了“ this”,并确认存在有效的“ thing”属性(如果没有,则该服务将不会启动)。
那么我有默认的bean名称算法错误吗?似乎难以置信,因为我还对“ JMXDemonstration”,“ name”和“ George”进行了测试,并且效果很好。
更新:
另请注意,调用“ applicationContext.getBean(SomeRandomThing.class)”将返回该类的bean实例,并且还调用“ applicationContext.getBeanDefinitionNames()”将返回不包含“ SomeRandomThing”的数组,但它确实包含“ JMXDemonstration” 。
为什么SomeRandomThing可以通过自动装配和通过类型而不是通过其bean名称来作为bean使用?
更新:
哦,因为bean名称是“ someRandomThing”,而不是“ SomeRandomThing”。我想本来应该是前者,但是当我看到“ JMXDemonstration”的bean名称是“ JMXDemonstration”时,我以为是“ SomeRandomThing”,而不是“ someRandomThing”。
最佳答案
豆命名
@Component是类级别的注释。在组件扫描期间,Spring Framework自动检测带有@Component注释的类。
@Component
class CarUtility {
// ...
}
缺省情况下,此类的Bean实例与具有小写首字母的类名称具有相同的名称。最重要的是,我们可以使用此批注的可选value参数指定其他名称。
基于注释的配置
对于基于构造型注释的Bean,如果未使用构造型注释的value字段显式指定名称,则该名称再次由
AnnotationBeanNameGenerator
生成,它是BeanNameGenerator策略接口here的实现。如果注释的值不表示bean名称,则将基于类的短名称(首字母小写)构建一个适当的名称。例如:
com.xyz.FooServiceImpl -> fooServiceImpl
通过在类路径中进行组件扫描,Spring会按照前面描述的规则为未命名的组件生成Bean名称:本质上,采用简单的类名称并将其初始字符转换为小写。但是,在(不寻常的)特殊情况下,如果有多个字符并且第一个和第二个字符均为大写字母,则会保留原始大小写。这些规则与doc java.beans.Introspector.decapitalize(Spring在此使用)定义的规则相同。