@ComponentScan比較


 

ComponetScan 定義掃描規則

  1. value:指定要掃描的包
  2. excludeFilters=Filter[] 指定掃描的時候按照什么規則排除哪些組件。
  3. includeFilters=Filter[] 指定掃描的時候只需要包含哪些組件。(注意的是包掃描默認的是掃描所有的,也就是use-default-filters=”true”,所以需要設置為false。 這個和配置文件一樣)
  • FilterType.ANNOTATION :按照注解的方式
  • FilterType.ASSIGNABLE_TYPE:按照給定的類型
  • FilterType.CUSTOM:使用自定義規則。 使用這個需要是TypeFilter的實現類
  • FilterType.CUSTOM使用 案例如下:
  • FilterType.ASPECTJ:使用ASPECTJ表達式(基本用不到) 
  • FilterType.REGEX :使用正則表達式

例子

@Configuration
@ComponentScan(value = "feilong.example", useDefaultFilters = true, excludeFilters = {
        //過濾掉具體的注解下所有類
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),
//        //過濾掉具體的類
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {ConfigTest2.class})
},
        //includeFilter里面的Filter是並集
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
        }
)
public class MainConfig {

    @Bean
    public Person person() {
        return new Person("feilong", 20);
    }
}

 

類MyTypeFilter  是自定義Filter, 注意: 之前被過濾掉的類如果再自定義Filter中符合要求, 也會被重新放到IOC容器中.

public class MyTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {

        //獲取注解metaData
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        Resource resource = metadataReader.getResource();

        //獲取當前類信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        String strClassName = classMetadata.getClassName();

        System.out.println("通過自定義規則 ==>>>> " + strClassName);
        
        //返回true的類會被注冊進IOC
        return strClassName.contains("Controller");

    }
}

 


@Import[快速的給容器中導入一個組件] 

@Import的三種用法:

(1)、 @Import(要導入容器中的組件);容器中就會自動的注冊這個組件,id默認是全類名
(2)、 ImportSelector :返回需要的組件的全類名的數組;
(3)、 ImportBeanDefinitionRegistrar : 手動注冊bean到容器中

 1. 組件注冊-@Import-給容器中快速導入一個組件

定義兩個POJO類

public class Color {
}

public class Red {
}

 

 

將此類對應的Bean導入IOC容器

@Configuration
@ComponentScan(value = "feilong.example")
@Import({Color.class, Red.class})
public class MainConfig {
}

 

2. 使用ImportSelector

創建自定義MyImportSelector , 在方法selectImports 中返回要注入的類

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"feilong.example.springbootlearn.Color","feilong.example.springbootlearn.Red"};
    }
}

 

將自定義ImportSeletor加入配置文件

@Configuration
@ComponentScan(value = "feilong.example")
@Import(MyImportSelector.class)
public class MainConfig {
}

 

3. 使用 ImportBeanDefinitionRegistrar接口, 

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        registry.registerBeanDefinition("green", new RootBeanDefinition(Green.class));
    }
}

 

 

將自定義ImportSeletor加入配置文件

@Configuration
@ComponentScan(value = "feilong.example")
@Import({MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
}

 

執行結果如下

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
feilong.example.springbootlearn.Color
feilong.example.springbootlearn.Red
person
person3
green

 


 使用FactoryBean注解

創建自定義的一個FactoryBean

public class MyColorFactoryBean implements FactoryBean<Color> {
    @Override
    public Color getObject() throws Exception {
        System.out.println("Creating Color Object by MyColorFactoryBean...");
        return new Color();
    }

//控制是否為單例 
// true:表示的就是一個單實例,在容器中保存一份 
// false:多實例,每次獲取都會創建一個新的bean
    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }
}

 

配置為Bean

@Configuration
@ComponentScan(value = "feilong.example")
public class MainConfig {

    @Bean
    public Person person() {
        return new Person("feilong", 20);
    }

    @Bean("person3")
    public Person personCondition() {
        return new Person("feilong", 30);
    }

    @Bean
    public MyColorFactoryBean colorFactoryBean(){
        return new MyColorFactoryBean();
    }
}

 

測試

public class MainTest {
    public static void main(String[] args) throws InterruptedException {

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

        String[] strName = ((AnnotationConfigApplicationContext) applicationContext).getBeanDefinitionNames();

        for (String s : strName) {
            System.out.println(s);
        }

    //此處獲取的是getObject對象, 即Color對象
        Color c = (Color) applicationContext.getBean("colorFactoryBean");
     //此處獲取的是BeanFactory工廠對象本身
        MyColorFactoryBean myColorFactoryBean =(MyColorFactoryBean) applicationContext.getBean("&colorFactoryBean");
        System.out.println(c);
        System.out.println(myColorFactoryBean);
    }
}

/*
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
person3
colorFactoryBean
Creating Color Object by MyColorFactoryBean...
feilong.example.springbootlearn.Color@2a32de6c
feilong.example.springbootlearn.MyColorFactoryBean@7692d9cc
*/

 

 

注意, 使用FactoryBean(工廠Bean) 默認獲取到的是工廠Bean調用方法getObject()獲取到的對象, 如果要想獲取到原來的Bean工廠本身,需要加上&, 


 Bean生命周期

* 容器管理bean的生命周期:
  * 我們可以自定義初始化方法和銷毀的方法:容器在bean進行到當前的生命周期的時候,來調用我們自定義的初始化方法和銷毀方法
* 構造(對象創建):
  * 單實例:在容器啟動的時候創建對象
  * 多實例:在每次獲取的時候來創建對象
* 初始化方法:
  * 對象創建完成,並賦值好,調用初始化方法
* 銷毀方法:
  * 單實例的bean:在容器關閉的時候進行銷毀
  * 多實例的bean:容器不會管理這個bean,容器不會調用銷毀的方法


生命周期-InitializingBeanDisposableBean

定義測試類: 

public class CarLifeCycle implements InitializingBean {
    public CarLifeCycle() {
        System.out.println("CarLifeCycle constructor...");
    }

    public void init() {
        System.out.println("CarLifeCycle...init...");
    }

    public void destroy() {
        System.out.println("CarLifeCycle...destroy...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("接口 InitializingBean # afterPropertiesSet ");
    }
}

 

定義MyBeanPostProcessor

public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + " => MyBeanPostProcessor .. before");
        return bean;
    }
    
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + " => MyBeanPostProcessor .. after");
        return bean;
    }
}

 

注入IOC

@Configuration
@ComponentScan(value = "feilong.example")
public class MainConfig {

    @Bean(initMethod = "init")
    public CarLifeCycle carLifeCycle(){
        return new CarLifeCycle();
    }
}

 

執行程序

CarLifeCycle constructor...
carLifeCycle => MyBeanPostProcessor .. before
接口 InitializingBean # afterPropertiesSet 
CarLifeCycle...init...
carLifeCycle => MyBeanPostProcessor .. after

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM