目录
- 前言
- 1. 基本知识
- 2. 详细分析
- 3. Demo
- 3.1 简单Bean配置
- 3.2 属性配置
- 3.3 多条件配置
- 4. 实战拓展
前言
Java的基本知识推荐阅读:
- java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
- Spring框架从入门到学精(全)
拓展应用补充阅读:@Configuration注解使用
1. 基本知识
在Java和Spring框架中,@Configuration
注解用于定义配置类,这些类可以替代传统的XML配置文件
- 是Spring的一部分,用于创建和管理bean,提供了更灵活和强大的配置机制
- 配置类包含了一个或多个@Bean方法,这些方法返回要在Spring容器中管理的bean
基本示例如下:
AppConfig类被标注为一个配置类,并且定义了一个myService方法,该方法返回一个MyService实例
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}
}
自动装配:
配置类中的bean可以自动装配到其他bean中
@Configuration
public class AnotherConfig {private final MyService myService;@Autowiredpublic AnotherConfig(MyService myService) {this.myService = myService;}@Beanpublic AnotherService anotherService() {return new AnotherServiceImpl(myService);}
}
2. 详细分析
注解继承与组合:
@Configuration类可以使用其他Spring注解,如@ComponentScan和@Import,来扫描组件或导入其他配置类
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {// Bean定义
}@Configuration
@Import(AppConfig.class)
public class MainConfig {// 主要配置
}
代理机制:
@Configuration类在Spring容器启动时会通过CGLIB动态代理机制生成代理类,以确保@Bean方法只被调用一次,从而保证单例bean的行为
@Configuration
public class ConfigClass {@Beanpublic MyBean myBean() {return new MyBean();}@Beanpublic AnotherBean anotherBean() {// myBean() 方法将返回相同的实例,而不会创建新实例return new AnotherBean(myBean());}
}
条件化配置:
使用@Conditional注解,可以根据某些条件来决定是否创建某个bean
@Configuration
public class ConditionalConfig {@Bean@Conditional(MyCondition.class)public MyBean conditionalBean() {return new MyBean();}
}
环境和属性配置:
使用@PropertySource和@Value注解可以将外部属性文件中的值注入到配置类中
@Configuration
@PropertySource("classpath:application.properties")
public class PropertyConfig {@Value("${my.property}")private String myProperty;@Beanpublic PropertyBean propertyBean() {return new PropertyBean(myProperty);}
}
3. Demo
3.1 简单Bean配置
总体完整的Demo如下:
// AppConfig.java
package com.example.demo;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic MyService myService() {return new MyService();}@Beanpublic MyController myController() {return new MyController(myService());}
}// MyService.java
package com.example.demo;public class MyService {public String sayHello() {return "Hello, World!";}
}// MyController.java
package com.example.demo;public class MyController {private final MyService myService;public MyController(MyService myService) {this.myService = myService;}public String greet() {return myService.sayHello();}
}// AppTest.java
package com.example.demo;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AppTest {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);MyController controller = context.getBean(MyController.class);System.out.println(controller.greet()); // 输出: Hello, World!}
}
最终执行结果如下:
3.2 属性配置
// AppConfig.java
package com.example.demo;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {@Value("${app.message}")private String message;@Beanpublic MessageService messageService() {return new MessageService(message);}
}// MessageService.java
package com.example.demo;public class MessageService {private final String message;public MessageService(String message) {this.message = message;}public String getMessage() {return message;}
}// AppTest.java
package com.example.demo;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AppTest {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(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.java
package com.example.demo;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Bean@Conditional(MyCondition.class)public ConditionalService conditionalService() {return new ConditionalService();}
}// MyCondition.java
package com.example.demo;import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;public class MyCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 返回true时才会创建ConditionalService beanreturn true;}
}// ConditionalService.java
package com.example.demo;public class ConditionalService {public String getMessage() {return "Conditional Service is active!";}
}// AppTest.java
package com.example.demo;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AppTest {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(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)
public class DataPermissionConfiguration {@Beanpublic DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() {return rule -> {// deptrule.addDeptColumn(AdminUserDO.class);rule.addDeptColumn(DeptDO.class, "id");rule.addDeptColumn(AppointmentCommissionDO.class, "dept_id");// userrule.addUserColumn(AdminUserDO.class, "id");rule.addUserColumn(AppointmentCommissionDO.class, "user_id");};}}