1. 程式人生 > >Spring註解驅動開發——設定Bean屬性和動態註冊Bean

Spring註解驅動開發——設定Bean屬性和動態註冊Bean

1、@Scope設定元件作用域

@Configuration
public class MainConfigA {
    @Bean("person")
    @Scope("singleton")
    public Person person(){
        return new Person("張三丰",25);
    }
}
public class JuitTest {
    @Test
    public void test(){
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfigA.class);

        Person person = (Person)context.getBean("person");
        Person person1 = (Person)context.getBean("person");
        System.out.print(person == person1);//true
    }

}

@Scope的值:

    singleton:單例,預設值,每次都返回同一個物件,該物件是在容器啟動的時候建立的,在使用的時候直接從容器中獲取

    prototype:多例項,每次都新建立一個物件,物件不會在容器啟動時建立,而是在獲取物件時建立,每次獲取都建立一個新物件

    request:一個請求範圍內只建立一個物件

    session:一次會話範圍內只建立一個物件

@Scope註解也可以在元件的類名上標註:

@Component
@Scope("prototype")
public class Person {

	public Person() {
		System.out.println("Person Constructor");
	}

}
@Scope("prototype") public class Person { public Person() { System.out.println("Person Constructor"); } }

2、@Lazy註解實現元件Bean的懶載入

單例項的Bean物件預設在容器啟動的時候建立,可以設定懶載入使Bean的建立時機延後至第一次獲取的時候建立和初始化,懶載入僅作用於單例項(singleton)的Bean

@Configuration
@ComponentScan(value="com.bdm",useDefaultFilters = false,includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {BdmTypeFilter.class})})
public class MainConfig {

    @Bean
    @Lazy
    public Person person() {
        return new Person("lisi", 12);
    }
}

3、@Conditional:按照條件動態註冊Bean

public class JunitTest{

	ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
	
	@Test
	public void test(){
		Map<String,Person> persons = context.getBeansOfType(Person.class);
		System.out.print(persons);
		ConfigurableEnvironment environment = context.getEnvironment();//獲取執行環境
		String osName = environment.getProperty("os.name");//獲取作業系統名稱
	}
}

從這個測試類獲取Bean的方式可以看出Spring容器是將Bean的物件放在了Map中,而且同一個型別的bean可能會有多個(id不同),id為key、bean為value,另外通過ApplicationContenxt的物件可以獲取當前的執行環境資訊,在呼叫context.getBeansOfType(Person.class)方法時會建立所有型別為Person的物件

使用@Conditional註解需自定義Condition:實現Condition介面

public class MyCondition implements Condition {

	// context:判斷條件使用的上下文
	// metaData:使用該註解的類的註解資訊
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// 執行時的資訊以及環境變數、虛擬機器的變數
		Environment environment = context.getEnvironment();
		String property = environment.getProperty("os.name");
		if(property.toLowerCase().contains("Windows"))
			return true;
//		// 建立和裝配Bean的工廠
//		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//		// 類載入器
//		ClassLoader classLoader = context.getClassLoader();
//		// 所有的bean定義都在該類中註冊 也可以使用該物件註冊Bean
//		BeanDefinitionRegistry registry = context.getRegistry();
		return false;
	}

}

容器Bean中使用@Conditional註解:使person類僅會在windows系統中才會建立

@Configuration
public class MainConfig {

	@Bean
	@Conditional({MyCondition.class})
	public Person person(){
		return new Person("張三",12);
	}
	
	@Bean
	public Person person1(){
		return new Person("李四",13);
	}
}@Conditional({MyCondition.class})
	public Person person(){
		return new Person("張三",12);
	}
	
	@Bean
	public Person person1(){
		return new Person("李四",13);
	}
}

@Conditional註解可以標註在配置類上也可以標註在@Bean註解的方法上,作用的範圍不同,標註在類上時影響整個容器Bean

@Conditional的值是一個Condition型別的陣列,Condition是一個介面,有一個matches方法,該方法中有兩個引數:

    ConditionContext:通過此型別的引數可以獲取執行環境、Bean工廠等資訊

    AnnotatedTypeMetadata:通過此型別的變數可獲取到使用@Conditional註解的類的註解資訊