目录
前言:这篇文章主要介绍了@Configuration与@Component作为配置类的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
1.@Configuration注解的类:
@Configuration
public class test {
@Bean
public User getUser1(){
return User.builder().id(6).aBC("6").address("6").name("6").num(6).build();
}
@Bean
public User getUser2(){
return User.builder().id(7).aBC("7").address("7").name("7").num(7).build();
}
@Bean
public User getUser3( ){
return getUser1();
}
@Bean
public User getUser4(){
return getUser2();
}
}
2.@Component注解的类:
@Component
public class test {
@Bean
public User getUser1(){
return User.builder().id(6).aBC("6").address("6").name("6").num(6).build();
}
@Bean
public User getUser2(){
return User.builder().id(7).aBC("7").address("7").name("7").num(7).build();
}
@Bean
public User getUser3( ){
return getUser1();
}
@Bean
public User getUser4(){
return getUser2();
}
}
3.更改注释分别进行测试
public class UserServiceTest extends ReadwriteApplicationTests {
@Resource
User getUser1;
@Resource
User getUser2;
@Resource
User getUser3;
@Resource
User getUser4;
@Test
public void test1(){
System.out.println(getUser1==getUser3);
System.out.println(getUser2==getUser4);
System.out.println(getUser1);
System.out.println(getUser2);
System.out.println(getUser3);
System.out.println(getUser4);
}
}
4.结果
4.1 @Component的结果
false
false
User(id=6, num=6, name=6, address=6, aBC=6)
User(id=7, num=7, name=7, address=7, aBC=7)
User(id=6, num=6, name=6, address=6, aBC=6)
User(id=7, num=7, name=7, address=7, aBC=7)
4.2 @Configuration的结果
true
true
User(id=6, num=6, name=6, address=6, aBC=6)
User(id=7, num=7, name=7, address=7, aBC=7)
User(id=6, num=6, name=6, address=6, aBC=6)
User(id=7, num=7, name=7, address=7, aBC=7)
区别就在这里:可以看到@Configuration注解的
System.out.println(getUser1==getUser3);
true
System.out.println(getUser2==getUser4);
true
他们是同一个实例,同一个对象。
而@Component注解的
System.out.println(getUser1==getUser3);
false
System.out.println(getUser2==getUser4);
false
他们并不是同一个实例,是新对象,虽然内容一致。
5.分析
你点开@Configuration会发现其实他也是被@Component修饰的,因此context:component-scan/ 或者 @ComponentScan都能处理@Configuration注解的类。
@Configuration标记的类必须符合下面的要求:
配置类必须以类的形式提供(不能是工厂方法返回的实例),允许通过生成子类在运行时增强(cglib 动态代理)。
配置类不能是 final 类(没法动态代理)。
配置注解通常为了通过 @Bean 注解生成 Spring 容器管理的类,
配置类必须是非本地的(即不能在方法中声明,不能是 private)。
任何嵌套配置类都必须声明为static。
@Bean 方法可能不会反过来创建进一步的配置类(也就是返回的 bean 如果带有
@Configuration,也不会被特殊处理,只会作为普通的 bean)。
但是spring容器在启动时有个专门处理@Configuration的类,会对@Configuration修饰的类cglib动态代理进行增强,这也是@Configuration为什么需要符合上面的要求中的部分原因,那具体会增强什么呢?
这里是个人整理的思路 如果有错请指点
getUser3()中调用了getUser1(),因为是方法那必然getUser3()生成新的User.build(),所以动态代理增加就会对其进行判断如果getUser3()中调用的方法还有@Bean修饰,那就会直接调用spring容器中的getUser1实例,不再调用getUser1(),那必然是一个对象了,因为spring容器中的bean默认是单例。不理解比如xml配置的bean
<bean id="country" class="com.hhh.demo.Country" scope="singleton"/>
这里scope默认是单例。
但是如果我就想用@Component,那没有@Component的类没有动态代理咋办呢?
5.1 @Component的类没有动态代理,但可以用@Qualifier或者@Resource
@Component
public class test {
@Resource
private User getUser1;
@Bean
public User getUser1(){
return User.builder().id(6).aBC("6").address("6").name("6").num(6).build();
}
@Bean
public User getUser2(){
return User.builder().id(7).aBC("7").address("7").name("7").num(7).build();
}
@Bean
public User getUser3(){
return getUser1;
}
@Bean
public User getUser4(@Qualifier("getUser2") User user){
return user;
}
}
这样就保证是同一个User实例了
顺便说说一般情况下其实不太影响结果,虽然不是同一个实例,但是内容是相同的。