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
    }

总结

给容器中注册组件

  1. 包扫描 + 组件标注注解(@Controller等)
  2. @Bean 导入的第三方包里面的组件
  3. @Import
    • @Import
    • ImportSelector:返回需要导入的组件的全类名数组
    • ImportBeanDefinitionRegistrar:手动注册bean到容器
  4. 使用Spring提供的FactoryBean(工厂Bean)
posted @ 2020-09-13 16:06  Jimmyhe  阅读(312)  评论(0编辑  收藏  举报