spring注解驱动开发(二):spring中的@Lazy、@Scope、@Conditional注解

上一篇讲了@Bean、@Configuration、@ComponentScan,通过这三个注解,我们可以完成基本的容积组件的注册,这篇是上一篇的深入,是对注入到容器中的bean做更一步的认识。包括bean的作用范围、加载时机以及在什么条件下祖册bean。

1. bean的作用范围,使用@Scope调整作用域

    在spring中注入的实例默认是单实例:

        * singleton:单实例,初始化容器会实例化bean,并将bean放入到容器中,等下次获取直接到容器中获得。

        * prototype:多实例,初始化容器不会实例化bean,每次获得bean时候就会初始化bean,每次获得的bean会不同。

        * request:同一次请求创建一个实例。

       * session:同一次session同一个实例。

     代码演示:

        新建配置类代码,User对象和之前的User对象一致,指定姓名和年龄。

@Configuration
public class MainConfig02 {

    /**
     *      * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
     *      * @see ConfigurableBeanFactory#SCOPE_SINGLETON 默认
     *      * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
     *      * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
     * @return
     *     String SCOPE_SINGLETON = "singleton";
     *     String SCOPE_PROTOTYPE = "prototype";
     *     request:同一次请求创建一个bean
     *     session:同一次会话创建一个bean
     *
     */
    @Bean
    @Scope("prototype")
    public User user(){
System.out.println("创建user------");
return new User("zhangsan",12); } }

        新建测试类

    @Test
    public void testScope() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig02.class);
        User u1 = (User)applicationContext.getBean("user");//1
        User u2 = (User)applicationContext.getBean("user");//2
        System.out.println(u1==u2);//3
    }

        输出的结果是false,当吧@Scope中的参数修改为single是返回为true.

2. @Scope小结

    1)看出@Scope可以控制bean的作用域,single表示容器启动到关闭期间只会生成一个bean而scope表示每一次请求会产生不同的bean。

    2)注释特使类中的1、2、3行,在@Scope("single")时,控制台会打印创建user,在@Scope("Scope")时,并不会打印创建user,打开测试类1处注释,这时候说明单实例bean是在容器创建的时候创建好对象并放入到IOC容器,多实例bean要在使用bean的时候才会创建对象。

3. @Lazy延迟加载

    容器创建的时候全部初始化单实例bean会拉长项目启动时间,单实例bean如果在容器创建没有用到,在初始化不让其实例化:

    @Lazy,单实例在容器初始化的时候创建对象,懒加载是容器初始化时候不创建对象,等到使用该bean的时候再创建对象。

   在单实例bean上使用@Lazy,可以使单实例bean在容器创建的时候不被初始化,只有在使用bean实例化。

    可以在单实实例user上加上@Lazy注解,注释测试中getBean()方法,初始化容器不会打印 创建user。在getBean执行的时候,打印这句话,说明bean延迟初始化。

4. @Conditional 条件注入bean

    @Conditional 满足一定条件将bean注册到容器中。在springboot大量使用,例如注解ConditionalOnMissingBean。

    @Conditional参数是实现Condition接口得类,如果想使用@Conditional,需要自定义类并实现Condition接口。

    代码示例。

    新建条件类实现Condition接口

public class LinuxCondition implements Condition {
    /**
     *
     * @param context  上下文环境,可作为判断条件
     * @param metadata 注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获得当前IOC使用的bean工厂
        context.getBeanFactory();
        //获得类加载器
        context.getClassLoader();
        //获取当前环境信息
        Environment environment = context.getEnvironment();
        //获取bean的注册类,可以注册、移除bean
        BeanDefinitionRegistry registry = context.getRegistry();
        // registry.containsBeanDefinition(""); 判断容器中包含bean
        String property = environment.getProperty("os.name");
        if(property.contains("linux"))
            return true;
        return false;
    }
}
LinuxCondition
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取当前环境信息
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Windows"))
            return true;
        return false;
    }
}
WindowsCondition

    测试类新增测试方法,根据os.name的值来选择需要注册的组件。

    @Test
    public  void testCondition(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig02.class);
        String property = applicationContext.getEnvironment().getProperty("os.name");
        System.out.println(property);
        Map<String, User> beansOfType = applicationContext.getBeansOfType(User.class);
        System.out.println(beansOfType);
    }

    @Conditional 放在方法上,表示当前bean按照条件判断

    @Conditional 放在类上,表示当前类中的所有方法生成的bean按照条件判断,是对类的统一设置
    可以设置虚拟机启动参数-Dos.name=linux,来指定运行环境。

posted @ 2019-03-22 14:06  i孤独行者  阅读(213)  评论(0)    收藏  举报