我正在研究一种实验方法,该方法将使用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在此使用)定义的规则相同。

10-01 05:14
查看更多