【spring 註解】第3篇:@Scope、@Lazy和@Conditional註解

一隻小小鳥發表於2018-08-11

@Scope

用於指定一個Bean的生命週期。

  • @Scope註解的作用相當於xml配置中的scope屬性
<!--scope的預設是-->
<bean id="person" class="com.sff.app.bean.Person" scope="prototype"/>
  • ConfigurableBeanFactory.SCOPE_SINGLETON:表示單例項的物件,在spring容器啟動的時候建立,以後每次獲取時都從容器中取。
@Configuration
public class AppConfig2 {
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    public Person person() {
        System.out.println("給spring ioc容器中新增bean");
        return new Person("Mate", 12);
    }
}

用單元測試獲取bean

public void test02() {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig2.class);

        System.out.println("spring ioc容器啟動完成");

        Person person = (Person) ctx.getBean("person");
        Person person1 = (Person) ctx.getBean("person");

        //==比較兩個物件的地址值
        System.out.println(person == person1);
    }

執行結果:
給spring ioc容器中新增bean
spring ioc容器啟動完成
true

我們獲取了Person物件兩次,但Person物件往容器中只新增了一下;

  • ConfigurableBeanFactory.SCOPE_PROTOTYPE:多例項的,容器啟動的時候不會建立Bean,每次呼叫Bean的建立方法都會建立一個例項Bean。
@Configuration
public class AppConfig2 {
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Person person() {
        System.out.println("給spring ioc容器中新增bean");
        return new Person("Mate", 12);
    }
}

用單元測試獲取bean

public void test02() {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig2.class);

        System.out.println("spring ioc容器啟動完成");

        Person person = (Person) ctx.getBean("person");
        Person person1 = (Person) ctx.getBean("person");

        //==比較兩個物件的地址值
        System.out.println(person == person1);
    }

執行結果:
spring ioc容器啟動完成
給spring ioc容器中新增bean
給spring ioc容器中新增bean
false

@Lazy

懶載入,針對的是單例項的Bean,容器啟動的時候不建立物件,第一次獲取Bean的時候建立並初始化物件。

@Configuration
public class AppConfig2 {
    @Lazy
    @Bean
    public Person person() {
        System.out.println("給spring ioc容器中新增bean");
        return new Person("Mate", 12);
    }
}

單元測試:

public void test02() {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig2.class);
        System.out.println("spring ioc容器啟動完成");
        ctx.getBean("person");
    }

執行結果:
spring ioc容器啟動完成
給spring ioc容器中新增bean

@Conditional

按照一定條件進行判斷,滿足條件就給容器註冊Bean。

  • 可以註解在Bean方法,表示滿足當前條件,這個Bean的註冊才生效。
  • 可以註解在配置類上,表示滿足當前條件,這個配置類中的所有Bean註冊才能生效。

假如現在要根據當前作業系統型別注入一個Person物件,如果是Mac OS就注入賈伯斯,如果是Windows系統就注入比爾蓋茲。

/*配置類*/
@Configuration
public class AppConfig2 {
    /*配置一個賈伯斯*/
    @Bean("Steve Jobs")
    public Person appleFounder() {
        return new Person("Steve Jobs", 40);
    }
    /*配置一個比爾蓋茲*/
    @Bean("Bill Gates")
    public Person winFounder() {
        return new Person("Bill Gates", 37);
    }
}

自定義注入條件,實現Condition介面

/**
 * mac環境時注入條件
 */
public class MacCondition implements Condition {
    /**
     * @param context  判斷條件能使用的上下文
     * @param metadata 註釋資訊
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

        /*獲取容器使用的beanFactory*/
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();

        /*獲取類載入器*/
        ClassLoader classLoader = context.getClassLoader();

        /*獲取bean定義的註冊類*/
        BeanDefinitionRegistry registry = context.getRegistry();

        /*獲取當前的環境資訊*/
        Environment environment = context.getEnvironment();

        if (environment.getProperty("os.name").contains("Mac")) {
            return true;
        }
        return false;
    }
}

/**
 * windows時注入條件
 */
public class WinCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        /*獲取當前的環境資訊*/
        Environment environment = context.getEnvironment();

        if (environment.getProperty("os.name").contains("Win")) {
            return true;
        }
        return false;
    }
}

單元測試:

public void test03() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig2.class);
        /*獲取所有的bean*/
        Map<String, Person> beansOfType = ctx.getBeansOfType(Person.class);
        System.out.println(beansOfType);
    }

執行結果中只注入了賈伯斯,因為當前的開發環境時Mac OS:

{Steve Jobs=Person(name=Steve Jobs, age=40)}

相關文章