目录
前言
Java的基本知识推荐阅读:
- java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
- Spring框架从入门到学精(全)
拓展应用补充阅读:@Configuration注解使用
1. 基本知识
在Java和Spring框架中,
@Configuration
注解用于定义配置类,这些类可以替代传统的XML配置文件
- 是Spring的一部分,用于创建和管理bean,提供了更灵活和强大的配置机制
- 配置类包含了一个或多个@Bean方法,这些方法返回要在Spring容器中管理的bean
基本示例如下:
AppConfig类被标注为一个配置类,并且定义了一个myService方法,该方法返回一个MyService实例
importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassAppConfig{@BeanpublicMyServicemyService(){returnnewMyServiceImpl();}}
自动装配:
配置类中的bean可以自动装配到其他bean中
@ConfigurationpublicclassAnotherConfig{privatefinalMyService myService;@AutowiredpublicAnotherConfig(MyService myService){this.myService = myService;}@BeanpublicAnotherServiceanotherService(){returnnewAnotherServiceImpl(myService);}}
2. 详细分析
注解继承与组合:
@Configuration类可以使用其他Spring注解,如@ComponentScan和@Import,来扫描组件或导入其他配置类
@Configuration@ComponentScan(basePackages ="com.example")publicclassAppConfig{// Bean定义}@Configuration@Import(AppConfig.class)publicclassMainConfig{// 主要配置}
代理机制:
@Configuration类在Spring容器启动时会通过CGLIB动态代理机制生成代理类,以确保@Bean方法只被调用一次,从而保证单例bean的行为
@ConfigurationpublicclassConfigClass{@BeanpublicMyBeanmyBean(){returnnewMyBean();}@BeanpublicAnotherBeananotherBean(){// myBean() 方法将返回相同的实例,而不会创建新实例returnnewAnotherBean(myBean());}}
条件化配置:
使用@Conditional注解,可以根据某些条件来决定是否创建某个bean
@ConfigurationpublicclassConditionalConfig{@Bean@Conditional(MyCondition.class)publicMyBeanconditionalBean(){returnnewMyBean();}}
环境和属性配置:
使用@PropertySource和@Value注解可以将外部属性文件中的值注入到配置类中
@Configuration@PropertySource("classpath:application.properties")publicclassPropertyConfig{@Value("${my.property}")privateString myProperty;@BeanpublicPropertyBeanpropertyBean(){returnnewPropertyBean(myProperty);}}
3. Demo
3.1 简单Bean配置
总体完整的Demo如下:
// AppConfig.javapackagecom.example.demo;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassAppConfig{@BeanpublicMyServicemyService(){returnnewMyService();}@BeanpublicMyControllermyController(){returnnewMyController(myService());}}// MyService.javapackagecom.example.demo;publicclassMyService{publicStringsayHello(){return"Hello, World!";}}// MyController.javapackagecom.example.demo;publicclassMyController{privatefinalMyService myService;publicMyController(MyService myService){this.myService = myService;}publicStringgreet(){return myService.sayHello();}}// AppTest.javapackagecom.example.demo;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassAppTest{publicstaticvoidmain(String[] args){ApplicationContext context =newAnnotationConfigApplicationContext(AppConfig.class);MyController controller = context.getBean(MyController.class);System.out.println(controller.greet());// 输出: Hello, World!}}
最终执行结果如下:

3.2 属性配置
// AppConfig.javapackagecom.example.demo;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.PropertySource;@Configuration@PropertySource("classpath:application.properties")publicclassAppConfig{@Value("${app.message}")privateString message;@BeanpublicMessageServicemessageService(){returnnewMessageService(message);}}// MessageService.javapackagecom.example.demo;publicclassMessageService{privatefinalString message;publicMessageService(String message){this.message = message;}publicStringgetMessage(){return message;}}// AppTest.javapackagecom.example.demo;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassAppTest{publicstaticvoidmain(String[] args){ApplicationContext context =newAnnotationConfigApplicationContext(AppConfig.class);MessageService service = context.getBean(MessageService.class);System.out.println(service.getMessage());// 输出配置文件中的app.message值}}// application.properties
app.message=Hello from properties!
截图如下:

3.3 多条件配置
// AppConfig.javapackagecom.example.demo;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Conditional;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassAppConfig{@Bean@Conditional(MyCondition.class)publicConditionalServiceconditionalService(){returnnewConditionalService();}}// MyCondition.javapackagecom.example.demo;importorg.springframework.context.annotation.Condition;importorg.springframework.context.annotation.ConditionContext;importorg.springframework.core.type.AnnotatedTypeMetadata;publicclassMyConditionimplementsCondition{@Overridepublicbooleanmatches(ConditionContext context,AnnotatedTypeMetadata metadata){// 返回true时才会创建ConditionalService beanreturntrue;}}// ConditionalService.javapackagecom.example.demo;publicclassConditionalService{publicStringgetMessage(){return"Conditional Service is active!";}}// AppTest.javapackagecom.example.demo;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassAppTest{publicstaticvoidmain(String[] args){ApplicationContext context =newAnnotationConfigApplicationContext(AppConfig.class);if(context.containsBean("conditionalService")){ConditionalService service = context.getBean(ConditionalService.class);System.out.println(service.getMessage());// 输出: Conditional Service is active!}else{System.out.println("Conditional Service is not active");}}}
截图如下:

4. 实战拓展
对于这个@Configuration注解,往往会配合proxyBeanMethods一起使用
proxyBeanMethods = true(默认行为):表示Spring会为配置类生成一个CGLIB代理对象,以确保每个@Bean方法只会被调用一次,并且返回相同的实例(单例模式) 这种方式可以确保@Bean方法间的依赖能够正确处理proxyBeanMethods = false:表示Spring不会为配置类生成代理对象,每次调用@Bean方法时都会返回一个新的实例 这种方式可以减少CGLIB代理的开销,适用于@Bean方法之间没有依赖关系的场景
Demo如下:
@Configuration(proxyBeanMethods = false)
是一个Spring的注解,用于标识一个类是配置类,同时指定该配置类中@Bean方法的代理行为
方法每次调用都会返回一个新的 DeptDataPermissionRuleCustomizer 实例
@Configuration(proxyBeanMethods =false)publicclassDataPermissionConfiguration{@BeanpublicDeptDataPermissionRuleCustomizersysDeptDataPermissionRuleCustomizer(){return rule ->{// dept
rule.addDeptColumn(AdminUserDO.class);
rule.addDeptColumn(DeptDO.class,"id");
rule.addDeptColumn(AppointmentCommissionDO.class,"dept_id");// user
rule.addUserColumn(AdminUserDO.class,"id");
rule.addUserColumn(AppointmentCommissionDO.class,"user_id");};}}
版权归原作者 码农研究僧 所有, 如有侵权,请联系我们删除。