@Bean注解和@Configuration、@Component注解组合使用的区别

目录
  • 一、@Bean的“full”模式和“lite”模式
  • 二、两种模式的差异
    • 1、“full”模式下@Bean方法互相调用
    • 2、“lite”模式下@Bean方法互相调用
  • 三、总结

一、@Bean的“full”模式和“lite”模式

在一般常见情况下,@Bean注解在@Configuration类中声明,称之为“full”模式;当@Bean注解和@Component注解组合使用时,称之为“lite”模式。

这两种组合使用的情况,初次看文档时没看明白,多看了几次又跑了测试代码,才大致理解了区别。

二、两种模式的差异

如果只是把@Bean注解用在方法上,并且各个@Bean注解的方法之间没有调用,上述两种模式达到的效果基本相同,都可以把@Bean注解方法返回的对象作为bean注册到容器中。

如果各个@Bean注解的方法之间有相互调用,那么两种模式就会有很大的区别-与full模式下的@Configuration不同,lite模式下 @Bean方法互相调用无法声明Bean之间的依赖关系。

这点在@Bean注解源码注释上也有说明。

1、“full”模式下@Bean方法互相调用

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
public class Config {

    @Bean()
    public C c(){
        return new C();
    }

    @Bean
    public B b(){
        return new B(c());
    }
}

类B:

public class B {
    public C c;
    public B(C a){this.c=a;}
    public void shutdown(){
        System.out.println("b close...");
    }
}

类C:

public class C {
    private String name;
    @PostConstruct
    public void init(){
        this.name = "I am a bean";
    }

    @Override
    public String toString(){
        return "c say:" + name;
    }
}

如上述所示代码,我们有两个类B和C,在@Configuration类中,使用两个@Bean方法分别定义bean b 和bean c,但是需要注意的是new B(c()) 所在的@Bean方法调用了另一个@Bean方法。

测试主程序类:

import com.dxc.opentalk.springtest.config.B;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy; 

@EnableAspectJAutoProxy
@ComponentScan("com.dxc.opentalk.springtest")
public class BootStrap {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext
                = new AnnotationConfigApplicationContext(BootStrap.class);
        B b = (B)applicationContext.getBean("b");
        System.out.println(b.c);
        System.out.println(applicationContext.getBean("c"));
        System.out.println(applicationContext.getBean("c").equals(b.c));
    }
}

程序输出结果:

c say:I am a bean
c say:I am a bean
true

可以看出bean c 被注入到了bean b 中,bean b中的成员 c 确实是Spring容器中的bean。(其实,debug程序跟踪Spring中的单例池更清晰,这里采用输出结果说明)

2、“lite”模式下@Bean方法互相调用

还是上面的代码,我们只把Config类上的注解更换成@Component,其余代码保持不变:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
public class Config {

    @Bean()
    public C c(){
        return new C();
    }

    @Bean
    public B b(){
        return new B(c());
    }
}

再看一下测试主程序类输出结果:

c say:null
c say:I am a bean
false

可以看到bean b中的c只是一个普通的c对象,并不是Spring容器中的bean(b中的c没有执行bean的初始化回调方法也和单例池中的c bean不相等)。所以这种模式下,@Bean方法互相调用不能完成bean之间相互依赖关系的注入。

三、总结

综上所述,在使用@Bean注解时需要注意两种模式的区别,一般情况下@Bean都是和@Configuration注解搭配使用的。

但是@Configuration注解的类会被Spring使用CGLIB子类化,所以@Configuration注解的类不能用 final 修饰,而@Component注解没有此限制。

如果使用@Bean注解和@Component注解组合需要完成bean之间相互依赖注入的话,官方推荐采用构造方法或者方法级别的依赖注入,如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Component
public final class Config {

    @Bean()
    public C c(){
        return new C();
    }
    @Bean
    public B b(C c){//构造方法注入
        return new B(c);
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Spring @Bean vs @Service注解区别

    今天跟同事讨论了一下在Spring Boot中,是使用@Configuration和@Bean的组合来创建Bean还是直接使用 @Service等注解放在类上的方式.笔者倾向于使用第一种,即@Configuration和@Bean的组合. 先来看一个例子,目标是创建SearchService的一个Bean. 直接使用@Service的方式: // SearchService.java package li.koly.search; import java.util.List; public in

  • JavaBean和SpringBean的区别及创建SpringBean方式

    目录 一:对象,JavaBean,SpringBean的区别 1.什么是JavaBean 2.什么是SpringBean 3.SpringBean和JAVABean的区别 二:如何定义一个SpringBean 1.通过ClassPathXmlApplicationContext 2.通过AnnotationConfigApplicationContext底层 3.通过BeanDefinition 4.通过FactoryBean 5.通过Supplier 一:对象,JavaBean,SpringB

  • Springboot @Configuration @bean注解作用解析

    这篇文章主要介绍了springboot @Configuration @bean注解作用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 @Configuration注解可以达到在Spring中使用xml配置文件的作用 @Bean就等同于xml配置文件中的<bean> 在spring项目中我们集成第三方的框架如shiro会在spring.xml配置文件中进行配置,例如: <!-- 配置shiro框架提供过滤器工厂 --> <

  • 一个@Component注解引发的大坑

    目录 一个@Component注解引发的大坑 问题是这样的 思考 对spring @component注解的理解 @Component注解的使用 注解的类 测试的类 一个@Component注解引发的大坑 首先,我们这个是用springboot架构来实现的业务 这是项目包结构和配置文件结构 这是定时需要执行的任务 这是我执行PromoCodeCMCJob这个定时器的报错信息 问题是这样的 加了两个MQ之后才报错的这个信息,当我执行启动PromoCodeCMCJob定时任务的时候就报错,报错信息如

  • @Bean注解和@Configuration、@Component注解组合使用的区别

    目录 一.@Bean的"full"模式和"lite"模式 二.两种模式的差异 1."full"模式下@Bean方法互相调用 2."lite"模式下@Bean方法互相调用 三.总结 一.@Bean的"full"模式和"lite"模式 在一般常见情况下,@Bean注解在@Configuration类中声明,称之为"full"模式:当@Bean注解和@Component注解

  • Spring @bean和@component注解区别

    目录 Spring 中的一些注解 2. Autowire 和 @Resource 的区别 3. 将一个类声明为 Spring 的 bean 的注解有哪些? 4. @Configuration :配置类注解 5. @ControllerAdvice :处理全局异常利器 6. @Component, @Repository, @Service 的区别 总结 本文打算介绍几个不太容易说出其区别,或者用途的 Spring 注解,比如 @Component 与 @Bean 的比较,@ControllerA

  • spring @Component注解原理解析

    这篇文章主要介绍了spring @Component注解原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.@controller 控制器(注入服务) 2.@service 业务(注入dao) 3.@repository dao(实现dao访问) 4.@component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>) 5.@Comp

  • 聊聊注解@controller@service@component@repository的区别

    目录 注解@controller@service@component@repository的区别 命名不一样主要是为了区分类的作用和所属层级: Spring中的主要注解 1. 组件类注解@Component.@Repository.@Service.@Controller[创建注解] 1.@Component 标注为一个普通的spring Bean类 2.@Repository 标注为一个DAO层的组件类 3.@Service 标注为Service层(业务逻辑层)的组件类 4.@Controll

  • 关于@Component注解的含义说明

    目录 一.注解分类 二.@Component 注解含义 三.基于@Component扩展的注解 四.component的扫描组件 五.方法初始化和销毁 1. @PostConstruct注解 2. @PreDestroy注解 3. 示例 一.注解分类 1.@controller:controller控制器层(注入服务) 2.@service:service服务层(注入dao) 3.@repository:dao持久层(实现dao访问) 4.@component:标注一个类为Spring容器的Be

  • 关于@Component注解下的类无法@Autowired问题

    目录 @Component注解下类无法@Autowired 这个问题心累 @Component注解下@Autowired报错 下面是我的解决方案 @Component注解下类无法@Autowired 这个问题心累 在把我的一个非Web程序迁移从Spring迁移到SpringBoot时,出现了在@Component注解下@Autowired的类为null的情况,也就是没注入成功,或者说是此类在bean加载之前就被调用了. 试了各种办法,修改扫描包,修改@Component注解等等,皆未成功,后来看

  • springboot中@component注解的使用实例

    目录 @component注解的使用 方式一 方式二 @component注解有什么作用 用一句话概括 @component注解的使用 配置响应头的内容. 方式一 直接在拦截器里配置响应头内容. /**  * 拦截器--用户身份确认.  */ public class RestInterceptor implements HandlerInterceptor {         private static final Logger log = LoggerFactory.getLogger(R

  • Java注解Annotation与自定义注解详解

    一:Java注解简介 开发中经常使用到注解,在项目中也偶尔会见到过自定义注解,今天就来探讨一下这个注解是什么鬼,以及注解的应用场景和如何自定义注解. 下面列举开发中常见的注解 @Override:用于标识该方法继承自超类, 当父类的方法被删除或修改了,编译器会提示错误信息(我们最经常看到的toString()方法上总能看到这货) @Deprecated:表示该类或者该方法已经不推荐使用,已经过期了,如果用户还是要使用,会生成编译的警告 @SuppressWarnings:用于忽略的编译器警告信息

  • @Configuration与@Component作为配置类的区别详解

    @Configuration注解的类: /** * @Description 测试用的配置类 * @Author 弟中弟 * @CreateTime 2019/6/18 14:35 */ @Configuration public class MyBeanConfig { @Bean public Country country(){ return new Country(); } @Bean public UserInfo userInfo(){ return new UserInfo(cou

随机推荐