Spring 声明配置类:@Configuration
文章目录
- @Configuration 注解说明
- @Configuration 注解属性说明
- value 属性
- proxyBeanMethods 属性
- proxyBeanMethods 属性值为 false 的情况
- proxyBeanMethods 属性值为 true 的情况
- @Component 注解与 @Configuration 注解的区别
@Configuration 注解说明
@Configuration
是 Spring 中 org.springframework.context.annotation
包下的一个注解。@Configuration
用于标记一个类为配置类。
在 Spring 中,配置类是一种特殊的类,用于定义 Spring 应用程序中的 Bean 与其他配置元素,例如拦截器、过滤器、拦截器栈等。使用 @Configuration
标记类后,Spring 会在启动时扫描这个类,并根据其中的配置创建与管理相应的 Bean。
@Configuration 注解属性说明
以下是 @Configuration 注解的源代码:
@Configuration
注解中包含两个属性,分别是 value
与 proxyBeanMethods
。
value 属性
value
属性用于指定该配置类 Bean 在 Spring IOC 容器中的名称。
例如,将一个 MyConfiguration
的类,注入为一个名为 myCustomConfiguration
的 Bean。
package test.config;import org.springframework.context.annotation.Configuration;@Configuration(value = "myCustomConfiguration")
public class MyConfiguration {// ...}
proxyBeanMethods 属性
而 proxyBeanMethods
属性则可以控制调用该配置类内部 @Bean
方法时返回的对象是否为单例。
proxyBeanMethods 属性值为 false 的情况
当 proxyBeanMethods
的属性值为 false 时,每次调用 @Bean
方法时,Spring 将使用 CGLIB 动态代理以确保返回的对象是单例。
以下是一个案例,说明 proxyBeanMethods 属性值为 false 时的情况。
-
定义一个名为 MyBean1 的普通类,并声明一个成员变量,通过构造方法可以将 MyBean2 类设置到成员变量中。
package test.config;import lombok.Data;@Data public class MyBean1 {private MyBean2 myBean2;public MyBean1(MyBean2 myBean2){this.myBean2 = myBean2;}}
-
定义一个名为 MyBean2 的普通类。
package test.config;public class MyBean2 { }
-
定义一个配置类,在配置类通过 @Bean 声明上述两个类。
package test.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration(proxyBeanMethods = false) public class MyConfiguration {@Beanpublic MyBean2 myBean2(){return new MyBean2();}@Beanpublic MyBean1 myBean1() {return new MyBean1(myBean2());}}
-
直接获取 IOC 容器中名为 myBean2 的 Bean 与通过名为 myBean1 获取 myBean2 的 Bean。
package test;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import test.config.MyBean1; import test.config.MyBean2;@SpringBootApplication public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);MyBean2 myBean2_1 = (MyBean2) context.getBean("myBean2");System.out.println(myBean2_1);MyBean1 myBean1 = (MyBean1) context.getBean("myBean1");MyBean2 myBean2_2 = myBean1.getMyBean2();System.out.println(myBean2_2);}}
-
执行结果:
上述执行结果说明获取到了不同的实例对象。
proxyBeanMethods 属性值为 true 的情况
proxyBeanMethods
属性默认值为 true。当 proxyBeanMethods
的属性值为 true 时,每次调用 @Bean
方法时,Spring 使用 CGLIB 动态代理确保返回对象是单例。
-
继续以上述案例为例,去掉
proxyBeanMethods
属性(使proxyBeanMethods
属性为默认值 true)。package test.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class MyConfiguration {@Beanpublic MyBean2 myBean2(){return new MyBean2();}@Beanpublic MyBean1 myBean1() {return new MyBean1(myBean2());}}
-
输出的结果为:
上述执行结果说明获取到了不同的实例对象。
@Component 注解与 @Configuration 注解的区别
@Component
与 @Configuration
虽然都用于声明一个类为被 Spring 管控的 Bean,都被它们声明的 Bean 有着本质上的区别。
它们的区别在于是否创建代理类。如果使用 @Configuration
修饰类(默认 proxyBeanMethods=true
情况下),Spring 将会为这个 Bean 创建一个代理类。该代理类会拦截所有被 @Bean
修饰的方法,在拦截的方法逻辑中,会从容器中返回所需要的单例对象,除非将 proxyBeanMethods
属性设置为 false
。而使用 @Component
注解修饰的类不会为这个 Bean 创建一个代理类,所以直接执行用户的方法每次都会返回一个新的对象。