美文网首页
Spring注解(@Scope @Lazy @Condition

Spring注解(@Scope @Lazy @Condition

作者: Godlike_4029 | 来源:发表于2019-03-21 02:30 被阅读0次

    @Scope注解指定注入容器的bean是单实例还是多实例的,默认情况下是单实例

    @Configuration
    public class MainConfig2 {
        @Scope("prototype")
        @Bean("person")
        public Person person(){
    
            return new Person("zhangsan",22);
        }
    }
    

    ConfigurableBeanFactory#SCOPE_PROTOTYPE
    @see ConfigurableBeanFactory#SCOPE_SINGLETON
    @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request
    @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION sesssion@return
    @Scope:调整作用域
    prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。
    每次获取的时候才会调用方法创建对象;
    singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。
    以后每次获取就是直接从容器(map.get())中拿,
    request:同一次请求创建一个实例
    session:同一个session创建一个实例
    对比Spring xml 配置

    <bean id="person" class="com.atguigu.bean.Person"  scope="prototype" >
           <property name="age" value="${}"></property>
           <property name="name" value="zhangsan"></property>
    </bean>
    

    @Scope("prototype") 指定多实例测试代码

       @Test
        public void test2(){
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
    //        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    //        for (String beanDefinitionName : beanDefinitionNames) {
    //            System.out.println(beanDefinitionName);
    //        }
    
            System.out.println("ioc容器创建完成");
            Object person = applicationContext.getBean("person");
            System.out.println(person);
            Object person1 = applicationContext.getBean("person");
            System.out.println(person1);
    
            System.out.println(person==person1);
    
        }
    

    测试结果如下(每次获取bean,都会创建一个新的对象)

    ioc容器创建完成
    Person constructor....
    Person [name=zhangsan, age=22, nickName=null]
    Person constructor....
    Person [name=zhangsan, age=22, nickName=null]
    false
    
    Process finished with exit code 0
    

    懒加载:@Lazy
    单实例bean:默认在容器启动的时候创建对象;
    懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;

    @Configuration
    public class MainConfig2 {
    
        @Scope("singleton")
        @Lazy
        //@Scope("prototype")
        @Bean("person")
        public Person person(){
            return new Person("zhangsan",22);
        }
    }
    

    @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean,Spring 底层大量使用的一个注解 可以标在类上,方法上

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Conditional {
        Class<? extends Condition>[] value();
    }
    

    向容器中注入 bean

    @Configuration
    public class MainConfig2 {
    
        @Scope("singleton")
        @Lazy
        //@Scope("prototype")
        @Bean("person")
        public Person person(){
    
            return new Person("zhangsan",22);
        }
    
        @Bean("linux")
        public Person person01(){
            return new Person("Tom",10);
        }
    
        @Bean("windows")
        public Person person02(){
            return new Person("Jack",30);
        }
    
    }
    

    案例:如果当前系统的是Linux就注入 bean(linux),是windows就注入 bean(windows)

    • LinuxCondition、WindowsCondition 两个类都实现Condition 接口
    public class LinuxCondition implements Condition {
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            // TODO是否linux系统
    
            //1、能获取到ioc使用的beanfactory
            ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
            //2、获取类加载器
            ClassLoader classLoader = conditionContext.getClassLoader();
            //3、获取当前环境信息
            Environment environment = conditionContext.getEnvironment();
            //4、获取到bean定义的注册类
            BeanDefinitionRegistry registry = conditionContext.getRegistry();
    
            String property = environment.getProperty("os.name");
    
            //可以判断容器中的bean注册情况,也可以给容器中注册bean
            boolean definition = registry.containsBeanDefinition("person");
            if(property.contains("linux")){
                return true;
            }
    
            return false;
        }
    }
    
    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;
        }
    
    }
    
    • 配置类中添加@Condition 注解 (标在方法上)
    @Configuration
    public class MainConfig2 {
    
        @Scope("singleton")
        @Lazy
        //@Scope("prototype")
        @Bean("person")
        public Person person(){
    
            return new Person("zhangsan",22);
        }
    
        @Conditional(LinuxCondition.class)
        @Bean("linux")
        public Person person01(){
            return new Person("linus",10);
        }
    
        @Conditional(WindowsCondition.class)
        @Bean("windows")
        public Person person02(){
            return new Person("bill",30);
        }
    
    }
    
    • 测试(当前环境是Windows)
    @Test
        public void test3(){
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
            String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    
            //获取系统当前环境
            Environment environment = applicationContext.getEnvironment();
            String property = environment.getProperty("os.name");
            System.out.println(property);
    
            for (String beanDefinitionName : beanDefinitionNames) {
                System.out.println(beanDefinitionName);
            }
    
            Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);
            System.out.println(beansOfType);
    
        }
    
    • 测试结果
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    person
    windows
    Person constructor....
    {person=Person [name=zhangsan, age=22, nickName=null], windows=Person [name=bill, age=30, nickName=null]}
    
    Process finished with exit code 0
    

    可以看到 由于是Windows环境,bean(Linux) 并没有注入到容器中

    • 如果@Conditional 注解标在类上,满足当前条件,这个类中配置的所有bean注册才能生效
    //类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
    @Conditional({WindowsCondition.class})
    @Configuration
    public class MainConfig2 {
    
        @Scope("singleton")
        @Lazy
        //@Scope("prototype")
        @Bean("person")
        public Person person(){
    
            return new Person("zhangsan",22);
        }
      ........
    }
    

    相关文章

      网友评论

          本文标题:Spring注解(@Scope @Lazy @Condition

          本文链接:https://www.haomeiwen.com/subject/cfkamqtx.html