- 添加了 @Configuration 的类是 SpringBoot 的配置类,这个配置类等价于 Spring 的 配置文件;在配置类中可以使用 @Bean 注解定义 Bean 对象;如下我们定义了一个 配置类
class AppConfig {
// 声明一个名为 user 的 Bean 对象
public User user() {
return new User();
}
}
public
- 配置类对于 SpringBoot 来说,也是一个组件;可以启动类中拿到容器验证一下容器中是否有该组件
class SpringbootStudyApplication {
public static void main(String[] args) {
// 1.返回 IOC 容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootStudyApplication.class, args);
// 2.查看容器里的组件
String[] beanNames = context.getBeanDefinitionNames();
for (String beanName : beanNames) {
if(beanName.equals("appConfig")) {
System.out.println("AppConfig 是一个组件");
break;
}
}
}
}
public
- 配置类中调用 Bean 对象定义方法可得到对应 Bean 对象,即使多次调用,返回的是同一个对象
class SpringbootStudyApplication {
public static void main(String[] args) {
// 1.返回 IOC 容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootStudyApplication.class, args);
// 2.返回 AppConfig 对象
AppConfig appConfig = (AppConfig)context.getBean("appConfig");
// $$EnhancerBySpringCGLIB$$9b3d45d3@3003697
System.out.println(appConfig);
// 3.调用 user() 方法拿出两个 user Bean 对象进行比较
User user1 = appConfig.user();
User user2 = appConfig.user();
System.out.println(user1 == user2); // true
System.out.println(user1); // @6826c41e
System.out.println(user2); // @6826c41e
}
}
public
这是因为配置类上添加了 @Configuration 注解,容器中的 appConfig Bean对象不是普通对象,而是一个代理对象(CGLIB 增强代理对象),从上面打印出的 appConfig 可以看出;代理对象调用 user() 方法,SpringBoot 总会检查 user() 返回的 User 对象在容器中是否已经存在,如果存在就直接返回容器中的 User Bean 对象
- 我们进入 @Configuration 注解,发现该注解除了 value 属性,还有一个 proxyBeanMethods 属性,且默认值为 true
boolean proxyBeanMethods() default true;
该配置表示添加了 @Configuration 的配置类中的所有方法都是代理对象方法,如果我们把该选项设置为 false,那么第 3 步中 user1 != user2;AppConfig 也不是代理对象,而是普通对象
class SpringbootStudyApplication {
public static void main(String[] args) {
// 1.返回 IOC 容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootStudyApplication.class, args);
// 2.返回 AppConfig 对象
AppConfig appConfig = (AppConfig)context.getBean("appConfig");
System.out.println(appConfig); // @20921b9b
// 3.调用 user() 方法拿出两个 user Bean 对象进行比较
User user1 = appConfig.user();
User user2 = appConfig.user();
System.out.println(user1 == user2); // false
System.out.println(user1); // @867ba60
System.out.println(user2); // @5ba745bc
}
}
public
所以,如果存在组件依赖的情况,例如:事务依赖于连接池,这里就必须要设置为 @Configuration(proxyBeanMethods = true);这也是事务失效的一个原因!如果组件之间没有依赖,可以设置proxyBeanMethods = false,这将有助于提高容器初始化速度。