@Component和@Configuration的区别

源码

@Configuration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;
}

@Component

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
String value() default “”;
}

分析

从上面的源码我们可以看出@Configuration底层其实也是@Component注解,但是在@Component多了下列代码

  boolean proxyBeanMethods() default true;

从Spring的官方我们找到了两个注解的说明:
The @Bean methods in a Spring component are processed differently than their counterparts inside a Spring @Configuration class. The difference is that @Component classes are not enhanced with CGLIB to intercept the invocation of methods and fields. CGLIB proxying is the means by which invoking methods or fields within @Bean methods in @Configuration classes creates bean metadata references to collaborating objects; such methods are not invoked with normal Java semantics but rather go through the container in order to provide the usual lifecycle management and proxying of Spring beans even when referring to other beans via programmatic calls to @Bean methods. In contrast, invoking a method or field in an @Bean method within a plain @Component class has standard Java semantics, with no special CGLIB processing or other constraints applying.
翻译后结果:
Spring组件中的@Bean方法的处理方式与Spring@Configuration类中的对应方法不同。不同之处在于@Component类没有使用CGLIB进行增强,以拦截方法和字段的调用。CGLIB代理是在@Configuration类中调用@Bean方法中的方法或字段来创建对协作对象的Bean元数据引用的方法;这些方法不是用普通的Java语义调用的,而是通过容器来提供SpringBean的常规生命周期管理和代理,即使通过对@Bean方法的编程调用引用其他Bean时也是如此。相比之下,在普通@Component类中调用@Bean方法中的方法或字段具有标准的Java语义,没有特殊的CGLIB处理或其他约束。

下面我们通过简单通俗的代码来理解:

@Configuration


@Configuration
public class MyTestConfig {
 
	@Bean
	public Driver driver() {
		Driver driver = new Driver();
		driver.setId(1);
		driver.setName("driver");
		driver.setCar(car());
		return driver;
	}
 
	@Bean
	public Car car() {
		Car car = new Car();
		car.setId(1);
		car.setName("car");
		return car;
	}

@Component

@Component
public class MyTestConfig {
 
	@Bean
	public Driver driver() {
		Driver driver = new Driver();
		driver.setId(1);
		driver.setName("driver");
		driver.setCar(car());
		return driver;
	}
 
	@Bean
	public Car car() {
		Car car = new Car();
		car.setId(1);
		car.setName("car");
		return car;
	}
 
}

public class TestMain {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
		ApplicationContext context = new AnnotationConfigApplicationContext(MyTestConfig.class);
 
		// 获取bean
		Driver driver = (Driver) context.getBean("driver");
 
		// 获取bean
		Car car = (Car) context.getBean("car");
 
		boolean result = driver.getCar() == car;
		System.out.println(result ? "同一个car" : "不同的car");
 
	}
 
}

@Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例。@Component则不会被代理,调用一次获取一个全新的对象

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值