【Spring註解】1、Spring元件註冊
1、@Configuration:
指定該註解的類是個配置類,對應之前的配置檔案
2、@Bean:
指定該方法作為一個Bean元件,它會往容器中註冊一個Bean元件;
其中型別為返回值,id預設為方法名;
也可以使用@Bean註解的name屬性,來自定義id。
3、@ComponentScans:
可以配置多個@ComponentScan。
3.1、@ComponentScan:
指定要掃描的包路徑
-
excludeFilters=Filter[]: 指定掃描的時候要排除的元件。
-
useDefaultFilters: 過濾策略,預設為true,即會自動掃描帶@Component註解(包括@Component,@Controller,@Service,@Repository註解的類)。
-
includeFilters=Filter[]: 指定掃描符合規則的元件,如果只是想掃描某些指定元件,需要將useDefaultFilters設為false,禁用預設的掃描策略。
3.1.1、Filter型別:
- FilterType.ANNOTATION: 按照註解
@Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
使用@Controller註解的類符合以上規則。
- FilterType.ASSIGNABLE_TYPE: 按照給定的型別
@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = xxx.class)
符合xxx.java的類符合以上規則。
- FilterType.ASPECTJ: 按照ASPECTJ表示式
- FilterType.REGEX: 按照正則表示式
- FilterType.CUSTOM
要使用該策略,類必須實現org.springframework.core.type.filter.TypeFilter介面。
public class MyTypeFilter implements TypeFilter {
/**
* metadataReader: 讀取到的當前正在掃描的類資訊
* metadataReaderFactory: 可以獲取到其他任何類資訊的工廠類
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// TODO Auto-generated method stub
//獲取當前類註解的資訊
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//獲取當前正在掃描的類資訊
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//獲取當前類的資源(類路徑)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println(">>>>>" + className);
//簡單測試,如果掃描的類名中包含了er,則匹配
if(className.contains("er")){
return true;
}
return false;
}
}
同時標註:
@Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
這樣,在掃描的時候會將包含"er"字母的類加入到容器中。
4、@Scope:
指定元件的作用域,預設為單例:singleton
singleton:單例項,當ioc容器啟動會呼叫方法建立物件並放到ioc容器中,而以後每次獲取物件的時候直接從ioc容器中獲取。
prototype:多例項,ioc容器啟動並不會去呼叫方法建立物件,而是在每次獲取的時候才會去呼叫方法建立物件,所以每次獲取的物件都是不一樣的。
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean
public Book book(){
System.out.println("建立book例項...");
return new Book();
}
@Bean
public Person person(){//預設單例項
System.out.println("建立person例項...");
return new Person("zhangsan", 20);
}
測試:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig2.class);
//單例項
Object obj1 = applicationContext.getBean("person");
Object obj2 = applicationContext.getBean("person");
System.out.println(obj1 == obj2);//輸出true
//多例項
Object obj3 = applicationContext.getBean("book");
Object obj4 = applicationContext.getBean("book");
System.out.println(obj3 == obj4);//輸出false
5、@Lazy:
懶載入:只針對於單例項物件
預設載入Bean是在容器啟動的時候就會去建立物件,並將其放入ioc容器中;而懶載入則相反,容器啟動時不建立物件,而是在第一次使用(獲取)物件的時候,才會去建立物件,再將其加入到ioc容器中,之後每次再獲取該物件的時候,直接從ioc容器中獲取,不再重新建立。
@Lazy
@Bean
public Book book2(){
System.out.println("建立book2例項...");
return new Book();
}
6、@Conditional:
該註解可以標註在類上,也可以標註在方法上
方法級別:根據條件建立bean,只有滿足條件才會建立bean;
類級別:根據條件建立配置類,只有滿足條件才會去建立配置類,如果不滿足,則不會建立該配置類,同時配置類裡的bean也就不會被建立。
配置類:
@Configuration
public class MyConfig3 {
@Conditional(WindowsCondition.class)
@Bean("bill")
public Person person1(){
return new Person("bill gates", 60);
}
@Conditional(LinuxCondition.class)
@Bean("linus")
public Person person2(){
return new Person("linus", 50);
}
}
LinuxCondition條件類:
//判斷是否是Linux系統
public class LinuxCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO Auto-generated method stub
//獲取到ioc使用的BeanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//獲取類載入器
ClassLoader classLoader = context.getClassLoader();
//獲取當前環境變數
Environment environment = context.getEnvironment();
//獲取到bean定義的註冊類
BeanDefinitionRegistry registry = context.getRegistry();
//獲取系統環境
String systemName = environment.getProperty("os.name");
if(systemName.contains("Linux")){
return true;
}
return false;
}
}
WindowsCondition條件類:
//判斷是否是Windows系統
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO Auto-generated method stub
// 獲取當前環境變數
Environment environment = context.getEnvironment();
// 獲取系統環境
String systemName = environment.getProperty("os.name");
if (systemName.contains("Windows")) {
return true;
}
return false;
}
}
這樣,使用不同的作業系統,建立的Bean也就不一樣。
7、Spring匯入元件的方式:
Spring匯入元件的方式:
1、使用註解@Component、@Controller、@Service、@Repository
2、使用@Bean匯入第三方元件
3、使用@Import快速匯入一個或多個第三方元件
3.1、指定類
3.2、使用ImportSelector介面
3.3、使用ImportBeanDefinitionRegistrar介面
4、 FactoryBean介面
7.1、@Import
7.1.1、指定類
假設有兩個顏色類:Red.java和Green.class,可以在配置類上使用@Import註解註冊該兩個類。
@Import({Red.class, Green.class})
這樣在Bean定義的登錄檔裡有其兩個元件,其元件的id為全類名。
7.1.2、ImportSelector介面
需要實現ImportSelector介面
public class MyImportSelector implements ImportSelector {
//返回值就是要匯入到容器中的元件全類名
//AnnotationMetadata:當前標註@Import註解的類的所有註解資訊
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// TODO Auto-generated method stub
//方法不要返回null
return new String[]{"org.com.cay.spring.annotation.color.Blue", "org.com.cay.spring.annotation.color.Yellow"};
}
}
匯入:
@Import({Red.class, Green.class, MyImportSelector.class})
這樣不僅會將@Import註解中指定的類加入到容器中,同樣會將MyImportSelector#selectImports中方法返回的全類名進行註冊到容器中。
7.1.3、ImportBeanDefinitionRegistrar介面
實現ImportBeanDefinitionRegistrar介面,實現registerBeanDefinitions方法,手動註冊bean。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:當前類的註解資訊
*
* BeanDefinitionRegistry:BeanDefinition註冊類
* 把所有需要新增到容器中的bean,手動通過{@link BeanDefinitionRegistry#registerBeanDefinition(String, BeanDefinition)}進行註冊
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// TODO Auto-generated method stub
//因為Yellow這個Bean是通過@Import匯入的,所以bean的id為全類名,所以這裡需要判斷全類名才行
boolean hasBean = registry.containsBeanDefinition("org.com.cay.spring.annotation.color.Yellow");
System.out.println(">>>>>>hasBean: " + hasBean);
if(hasBean){
BeanDefinition beanDefinition = new RootBeanDefinition(Tiger.class);
registry.registerBeanDefinition("tiger", beanDefinition);
}
}
}
新增該實現類到@Import屬性中:
@Import({ Red.class, Green.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class })
7.2、FactoryBean介面
實現FactoryBean介面
public class ColorFactory implements FactoryBean<Color>{
//返回一個Color物件,這個物件會新增到容器中
@Override
public Color getObject() throws Exception {
// TODO Auto-generated method stub
return new Color();
}
@Override
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return Color.class;
}
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return true;
}
}
並將該factoryBean註冊到容器中:
@Configuration
@Import({ Red.class, Green.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class })
public class MyConfig4 {
@Bean
public ColorFactory colorFactory(){
return new ColorFactory();
}
}
測試:
@Test
public void testFactoryBean(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig4.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
Arrays.asList(beanDefinitionNames).stream().forEach(System.out::println);
//獲取到的是實現FactoryBean介面後通過getObject返回的實際bean
Object bean = applicationContext.getBean("colorFactory");
System.out.println("bean的型別: " + bean.getClass());
//獲取factorybean自身bean
//org.springframework.beans.factory.BeanFactory.FACTORY_BEAN_PREFIX = "&";
Object bean2 = applicationContext.getBean("&colorFactory");
System.out.println("bean2的型別: " + bean2.getClass());
}
為何使用"&"?
package org.springframework.beans.factory;
public interface BeanFactory {
/**
* Used to dereference a {@link FactoryBean} instance and distinguish it from
* beans <i>created</i> by the FactoryBean. For example, if the bean named
* {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
* will return the factory, not the instance returned by the factory.
*/
String FACTORY_BEAN_PREFIX = "&";
//other...
}
====================打個廣告,歡迎關注====================
QQ: |
412425870 |
微信公眾號:Cay課堂 |
|
csdn部落格: |
http://blog.csdn.net/caychen |
碼雲: |
https://gitee.com/caychen/ |
github: |
https://github.com/caychen |
點選群號或者掃描二維碼即可加入QQ群:328243383(1群) |
|
點選群號或者掃描二維碼即可加入QQ群: |
|
--------------------- 作者:caychen 來源:CSDN 原文:https://blog.csdn.net/caychen/article/details/82887926?utm_source=copy 版權宣告:本文為博主原創文章,轉載請附上博文連結!