@Configuration@Bean@Component 注解

@Configuration 和 @Bean

Spring的官方团队说 @Component可以替代 @Configuration注解;@Bean注解只能写在方法上,表明使用此方法创建一个对象,并且放入 Spring 容器。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component  //看这里!!!
public @interface Configuration 
区别:

@Bean 注解主要用于方法上,有点类似于工厂方法,当使用了 @Bean 注解,我们可以连续使用多种定义bean时用到的注解,譬如用 @Qualifier 注解定义工厂方法的名称,用 @Scope 注解定义该 bean 的作用域范围,譬如是 singleton 还是 prototype 等。
Spring 中新的 Java 配置支持的核心就是 @Configuration 注解的类。这些类主要包括 @Bean 注解的方法来为 Spring 的 IoC 容器管理的对象定义实例,配置和初始化逻辑。
使用 @Configuration 来注解类表示类可以被 Spring 的 IoC 容器所使用,作为 bean 定义的资源。

/*
@Configuation等价于<Beans></Beans>
@Bean等价于<Bean></Bean>
*/
@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

这和 Spring 的 XML 文件中的非常类似

<beans>
    <bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
举例对比说明

在@Component类中使用方法或字段时不会使用CGLIB增强(及不使用代理类:调用任何方法,使用任何变量,拿到的是原始对象,后面会有例子解释)。而在@Configuration类中使用方法或字段时则使用CGLIB创造协作对象(及使用代理:拿到的是代理对象);当调用@Bean注解的方法时它不是普通的Java语义,而是从容器中拿到由Spring生命周期管理、被Spring代理甚至依赖于其他Bean的对象引用。在@Component中调用@Bean注解的方法和字段则是普通的Java语义,不经过CGLIB处理。

@Configuration
public static class Config {

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean());
    }
}
  • 第一个代码正常工作,正如预期的那样,SimpleBeanConsumer将会得到一个单例SimpleBean 的链接。
  • 第二个配置是完全错误的,因为 Spring 会创建一个SimpleBean的单例 bean,但是SimpleBeanConsumer将获得另一个SimpleBean实例(也就是相当于直接调用new SimpleBean(),这个 bean 是不归 Spring 管理的),既new SimpleBean()实例是 Spring 上下文控件之外的。
@Component
public static class Config {

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean());
    }
}

原因总结

使用 @Configuration,所有标记为 @Bean的方法将被包装成一个 CGLIB 包装器,它的工作方式就好像是这个方法的第一个调用,那么原始方法的主体将被执行,最终的对象将在 Spring 上下文中注册。所有进一步的调用只返回从上下文检索的 bean。
在上面的第二个代码块中,新的SimpleBeanConsumer(simpleBean())只调用一个纯 java 方法。为了纠正第二个代码块,我们可以这样做

@Component
public static class Config {
    @Autowired
    SimpleBean simpleBean;

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean);
    }
}

猜你喜欢

转载自www.cnblogs.com/mewcoder/p/12595110.html