Full @Configuration
和lite @Bean mode
是 Spring Java Config 中两个非常有意思的概念。
先来看一下官方文档关于这两者的相关内容:
相关定义
lite @Bean mode
:当@Bean
方法在没有使用@Configuration
注解的类中声明时称之为lite @Bean mode
Full @Configuration
:如果@Bean
方法在使用@Configuration
注解的类中声明时称之为Full @Configuration
有何区别
总结一句话,Full @Configuration
中的@Bean
方法会被CGLIB所代理,而 lite @Bean mode
中的@Bean
方法不会被CGLIB代理。
举个例子
有一普通Java类,现在分别使用Full @Configuration
和 lite @Bean mode
这两种模式注册到Spring容器中。
public class User {
public User() {
System.out.println("user create... hashCode :" + this.hashCode());
}
}
Full @Configuration
配置类:
@Configuration
public class AppConfig {
@Bean
public User user() {
return new User();
}
@Bean
public String name(User user) {
System.out.println(user.hashCode());
System.out.println(user().hashCode());
return "123";
}
}
主程序:
public class FullMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
User user = context.getBean(User.class);
System.out.println(user.hashCode());
context.close();
}
}
运行结果:
user create... hashCode :1709537756
1709537756
1709537756
1709537756
分析:@Bean
是在使用了@Configuration
注解的类上被声明的,属于Full @Configuration
。@Configuration
类中的@Bean
地方会被CGLIB进行代理。Spring会拦截该方法的执行,在默认单例情况下,容器中只有一个Bean,所以我们多次调用user()
方法,获取的都是同一个对象。
注意:被CGLIB的方法是不能被声明为private
和final
,因为CGLIB是通过生成子类来实现代理的,private
和final
方法是不能被子类Override的,也就是说,Full @Configuration模式下,@Bean
的方法是不能不能被声明为private
和final
,不然在启动时Spring会直接报错。
lite @Bean mode
配置类:
@Component
public class LiteAppConfig {
@Bean
public User user() {
System.out.println("user() 方法执行");
return new User();
}
@Bean
public String name(User user) {
System.out.println("name(User user) 方法执行");
System.out.println(user.hashCode());
System.out.println("再次调用user()方法: " + user().hashCode());
return "123";
}
}
主程序:
public class LiteMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LiteAppConfig.class);
User user = context.getBean(User.class);
System.out.println(user.hashCode());
context.close();
}
}
运行结果:
user() 方法执行
user create... hashCode :254413710
name(User user) 方法执行
254413710
user() 方法执行
user create... hashCode :1793329556
再次调用user()方法: 1793329556
254413710
分析:在lite @Bean mode
模式下, @Bean
方法不会被CGLIB代理,所以多次调用user()
会生成多个user对象。
使用建议
为了防止出现一些奇怪的问题,建议都使用Full @Configuration
。
欢迎关注个人公众号: