Spring注解开发之@Conditional和@Import
@Scope设置组件作用域
@Configuration
public class MainConfig2 {
@Bean("person2")
// value: 默认prototype,singleyon request同一个请求创建一个实例,session同一个session创建一个实例
// singleton时,ioc容器启动会调用方法创建对象到ioc中,以后就从容器中拿
// prototype: 启动不会创建,获取的时候才会创建实例
@Scope("prototype")
public Person person(){
return new Person("jack",32);
}
}
@Test
public void test02(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
// Object person = applicationContext.getBean("person"); 与注册的id不同会找不到报错
Object person1 = applicationContext.getBean("person2");
Object person2 = applicationContext.getBean("person2");
System.out.println(person1==person2); // scope prototype时会报错
}
}
@Lazy懒加载:
// 不加@Lazy
@Configuration
public class MainConfig2 {
@Bean("person2")
public Person person(){
System.out.println("创建了jack实例"); // 会打印
return new Person("jack",32);
}
}
// 有lazy注解
@Configuration
public class MainConfig2 {
@Bean("person2")
@Lazy
public Person person(){
System.out.println("创建了jack实例"); // 不会打印,只有第一次获取此bean的时候会打印
return new Person("jack",32);
}
}
@Test
public void test02(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
@Conditional根据条件加载
- 此注解如果标在类上,表示满足当前条件,这个类中配置的所有bean才会生效
配置类
@Configuration
// @Conditional(ConditionTest.class)
public class MainConfig2 {
@Conditional(ConditionTest.class)
@Bean("jazz")
public Person person01(){
return new Person("deron",24);
}
@Conditional(ConditionTest2.class)
@Bean("hornet")
public Person person02(){
return new Person("paul",22);
}
}
Condition
public class ConditionTest implements Condition {
/**
*
* @param conditionContext 判断条件能使用的上下文
* @param annotatedTypeMetadata 注释信息
* @return
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// 1.可以获取到ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
// 2.获取到类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
// 3.获取bean定义的注册类(可以获取容器中bean的注册情况,也可以给容器中注册bean)
BeanDefinitionRegistry registry = conditionContext.getRegistry();
// 4.获取当前环境信息
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
assert property != null;
return property.contains("Mac");
}
}
public class ConditionTest2 implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
assert property != null;
return property.contains("windows");
}
}
测试类
@Test
public void test03(){
String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
for (String s : beanNamesForType) {
System.out.println(s); // 根据你的操作系统实现注册
}
}
@Import导入组件
1. 根据Class导入
可以快速将类导入到容器中
自定义class
public class Color {
}
在配置类中可以快速导入到容器
@Configuration
@Import(Color.class)
public class MainConfig2 {
}
2. ImportSelector导入
根据全类名导入
@Import({Color.class, MyImportSelector.class})
public class MyImportSelector implements ImportSelector {
// 返回值就是导入到容器中的组件全雷鸣
/**
*
* @param annotationMetadata 当前标注@Import注解的类的所有信息
* @return
*/
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.hjj.bean.Red"};
}
}
3. MyImportBeanDefinitionRegistrar导入
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Blue.class);
registry.registerBeanDefinition("blue",rootBeanDefinition);
}
}
FactoryBean
定义一个工厂即成FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
// 返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
System.out.println("getObject");
return new Color();
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
配置
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
测试时打印结果
@Test
public void test4(){
printBeans(applicationContext);
System.out.println("======");
// 工厂bean获取的是getObject创建的对象
Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");
System.out.println(colorFactoryBean.getClass());
--》 class com.hjj.bean.Color
// 获取工厂bean
Object bean = applicationContext.getBean("&colorFactoryBean");
System.out.println(bean.getClass());
--》 class com.hjj.bean.ColorFactoryBean
}
总结
给容器中注册组件
- 包扫描 + 组件标注注解(@Controller等)
- @Bean 导入的第三方包里面的组件
- @Import
- @Import
- ImportSelector:返回需要导入的组件的全类名数组
- ImportBeanDefinitionRegistrar:手动注册bean到容器
- 使用Spring提供的FactoryBean(工厂Bean)