一.conditional
Spring4提供了一个更通用的基于条件的Bean的创建,即使用@Conditional注解。
@Conditional根据满足某一个特定条件创建一个特定的Bean。
实现方式:自定义一个类实现org.springframework.context.annotation.Condition接口,在其matches方法中写自己的校验方式
package com.wuml.component.conditional;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* @author by wml on 2019/10/17.
*/
public class SystemCondition implements Condition {
/**
* 采用网上较为普遍的配置 判定当前运行环境的系统是否是windows
* @param context
* @param metadata
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String property = context.getEnvironment().getProperty("os.name");
System.out.println("运行环境:"+property.toUpperCase());
if(property.toUpperCase().contains("WINDOWS")){
return true;
}
return false;
}
}
package com.wuml.component.conditional;
import com.wuml.component.bean.Worker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
* @author by wml on 2019/10/17.
*/
@Configuration
public class ConditionConfig {
@Bean
@Conditional({SystemCondition.class})
public Worker worker(){
Worker worker = new Worker();
worker.setName("wuml");
worker.setAge("18");
return worker;
}
}
package com.wuml.component.conditional;
import com.wuml.component.bean.Worker;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author by wml on 2019/10/17.
*/
public class ConditionMainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ConditionConfig.class);
Worker bean = annotationConfigApplicationContext.getBean(Worker.class);
System.out.println(bean);
}
}
测试结果
测试LINUX环境的话,我采用的是idea,对main方法设置VM options: -Dos.name=LINUX
此时运行就会出现没有这个bean定义
然后把代码中的WINDOWS改成LINUX
if(property.toUpperCase().contains("LINUX")){
return true;
}
再执行
二.import
根据import的组件注解源码中可以看到,它的value支持多种class设置进行注册bean
public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
1.手动添加组件到IOC容器;
2.实现ImportSelector接口
package com.wuml.component.imports;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* @author by wml on 2019/10/17.
*/
public class ImporterSelector implements ImportSelector {
/**
* Select and return the names of which class(es) should be imported
* @param importingClassMetadata
* @return
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.wuml.component.imports.ImportWater"};
}
}
3.实现ImportBeanDefinitionRegistrar(java8中引入了default关键字,在接口内部包含了一些默认的方法实现,在实现这个类的时候需要手动去看下需要实现的方法,编辑器不会提示需要实现的方法)
package com.wuml.component.imports;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* @author by wml on 2019/10/17.
*/
public class ImportBeanDef implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean importWater = registry.containsBeanDefinition("com.wuml.component.imports.ImportWater");
if(importWater){
System.out.println("有水----------加载鱼");
//有水才有鱼
registry.registerBeanDefinition("importFish",new RootBeanDefinition(ImportFish.class));
}
}
}
配置类:
package com.wuml.component.imports;
import com.wuml.component.bean.Worker;
import com.wuml.component.factorybean.FactoryBeanDolphin;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author by wml on 2019/10/17.
*/
@Configuration
/**
* @link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.**/
//Worker.class自定义注册,ImporterSelector.class实现ImportSelector接口,ImportBeanDef实现ImportBeanDefinitionRegistrar
@Import({Worker.class,ImporterSelector.class,ImportBeanDef.class})
public class ImportConfig {
}
测试类:
package com.wuml.component.imports;
import com.wuml.component.bean.Worker;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author by wml on 2019/10/17.
*/
public class ImportMainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ImportConfig.class);
String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
for(String str:beanDefinitionNames){
System.out.println(str);
}
Worker bean = annotationConfigApplicationContext.getBean(Worker.class);
bean.setName("999");
bean.setAge("1");
System.out.println(bean);
ImportWater importWater = annotationConfigApplicationContext.getBean(ImportWater.class);
importWater.setName("888");
importWater.setAge("2");
System.out.println(importWater);
ImportFish importFish = annotationConfigApplicationContext.getBean(ImportFish.class);
importFish.setName("777");
importFish.setAge("3");
System.out.println(importFish);
}
}
测试结果:
通过以上3种方式注册的worker,importWater,importFish都注册成功
3.Factorybean
BeanFacotry是spring中比较原始的Factory。如XMLBeanFactory就是一种典型的BeanFactory。原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。
Factorybean和ApplicationContext的区别:
ApplicationContext接口,它由BeanFactory接口派生而来,ApplicationContext包含BeanFactory的所有功能,ApplicationContext还提供了国际化处理、事件传递、Bean自动装配、各种不同应用层的Context实现;通常建议比BeanFactory优先
Factorybean和BeanFactory的区别(简单查阅了一下资料,此处简述):
BeanFactory是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范
平时使用最多的2中applicationContext(ClassPathXmlApplicationContext,AnnotationConfigApplicationContext)都是实现了BeanFactory。
FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。
注:要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&
package com.wuml.component.factorybean;
import lombok.Data;
/**
* @author by wml on 2019/10/17.
*/
@Data
public class Dolphin {
String name;
String age;
public Dolphin(){
}
public Dolphin(String name,String age){
this.age = age;
this.name = name;
}
}
package com.wuml.component.factorybean;
import org.springframework.beans.factory.FactoryBean;
/**
* @author by wml on 2019/10/17.
*/
public class FactoryBeanDolphin implements FactoryBean<Dolphin> {
@Override
public Dolphin getObject() throws Exception {
return new Dolphin("10","10");
}
@Override
public Class<?> getObjectType() {
return Dolphin.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
package com.wuml.component.factorybean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author by wml on 2019/10/17.
*/
@Configuration
public class BeanConfig {
@Bean("factoryBeanDolphin")
public FactoryBeanDolphin get(){
return new FactoryBeanDolphin();
}
}
package com.wuml.component.factorybean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author by wml on 2019/10/17.
*/
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
Dolphin bean = (Dolphin)annotationConfigApplicationContext.getBean("factoryBeanDolphin");
System.out.println(bean);
System.out.println(bean.getClass().getName());
Object factoryBeanDolphin = annotationConfigApplicationContext.getBean("&factoryBeanDolphin");
System.out.println(factoryBeanDolphin.getClass().getName());
}
}
运行结果: