编程式条件装配(一般不实用)
1.Profile (应用于配置文件)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
String[] value();
}
上个帖子中增加
// 小狗类的配置类
@Configuration
public class MyConfiguration {
@Bean
public Dog jinmao() {
return new Dog("金毛");
}
@Bean
public Dog demu() {
return new Dog("德牧");
}
@Bean
public Dog noname() {
return new Dog();
}
}
// 小狗类
public class Dog {
public Dog() {
System.out.println("我是狗的无参构造");
}
public Dog(String name) {
System.out.println("我是狗的有参构造, 狗的名字是" + name);
}
}
// 注解引入 小狗配置类
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({AnimalServiceImpl.class, MyConfiguration.class})
public @interface EnableMarket {
}
// 运行之前的test文件 最终结果 配置类中的信息都注册进来了
我是狗的有参构造, 狗的名字是金毛
我是狗的有参构造, 狗的名字是德牧
我是狗的无参构造
我是猫,我的名字是:小花
这次把配置类加上@Profile(“animal”)注解
@Configuration
@Profile("animal")
public class MyConfiguration {
@Bean
public Dog jinmao() {
return new Dog("金毛");
}
@Bean
public Dog demu() {
return new Dog("德牧");
}
@Bean
public Dog noname() {
return new Dog();
}
}
// 运行结果, 没有生效
我是猫,我的名字是:小花
接下来修改环境中的ActiveProfile属性
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
StartConfig.class);
ctx.getEnvironment().setActiveProfiles("animal");
}
// 输出结果为空 小狗配置类还是没有生效
以上代码中 没有生效的原因是:new AnnotationConfigApplicationContext()中传入了参数,所以直接就将所有的Bean注册完成了。
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
// 注册相关Bean
register(componentClasses);
// refresh生效
refresh();
}
// 无参构造
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
修改启动代码:
// 改代码按照AnnotationConfigApplicationContext 类的有参构造重构
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("animal");
// 之后再注册所有的Bean
ctx.register(StartConfig.class);
ctx.refresh();
}
// 输出结果
我是狗的有参构造, 狗的名字是金毛
我是狗的有参构造, 狗的名字是德牧
我是狗的无参构造
声明式条件装配
如下图配置
运行测试方法
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
StartConfig.class);
}
// 输出结果
我是狗的有参构造, 狗的名字是金毛
我是狗的有参构造, 狗的名字是德牧
我是狗的无参构造
上图debug之后
public abstract class AbstractEnvironment implements ConfigurableEnvironment {
@Override
public void setActiveProfiles(String... profiles) {
// debug此处 设置Profiles方法中读取到 profiles中有animal
Assert.notNull(profiles, "Profile array must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Activating profiles " + Arrays.asList(profiles));
}
synchronized (this.activeProfiles) {
this.activeProfiles.clear();
for (String profile : profiles) {
validateProfile(profile);
this.activeProfiles.add(profile);
}
}
}
}
将参数animal改为cat,输出结果为空。
实际中Profile的用处
// 配置数据源 按照环境配置数据源(编程式, 还有配置文件式 使用的比较多)
@Configuration
public class DataSourceConfiguration {
@Bean
@Profile("dev")
public DataSource devDataSource() {
return null;
}
@Bean
@Profile("test")
public DataSource testDataSource() {
return null;
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
return null;
}
}
@Conditional注解
@Conditional 是在 SpringFramework 4.0 版本正式推出的,它可以让 Bean 的装载基于一些指定的条件,换句话说,被标注 @Conditional 注解的 Bean 要注册到 IOC 容器时,必须全部满足 @Conditional 上指定的所有条件才可以。
常用的注解,也可以自己定义