Spring IOC容器底层常见注解使用

一、说明

  拥抱Springboot,基于各种读取配置类的形式,了解常见IOC底层注解实用。

二、注解详解demo

  2.1、配置定义bean 

@Configuration
public class MainConfig {

    /**
     * 注意,当 @Bean 没有指定value或者name的时候,默认的beanName为方法名。
     */
    @Bean
    public Person person2(){
        return new Person();
    }
}

  去容器中读取bean

public class MainTest {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println(context.getBean(Person.class));
        System.out.println(context.getBean("person2"));
    }
}

  2.2、配置类的@ComponentScan注解扫描

@Configuration
//@ComponentScan(basePackages = {"com.cfang.ioc.compantscan"})
@ComponentScan(basePackages = {"com.cfang.ioc.compantscan"},excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class}),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {UserService.class}),
        @ComponentScan.Filter(type = FilterType.CUSTOM, value = {CustomFilterType.class})
})
public class MainConfig {
}

  basePackages :配置基本扫描的包路径

       excludeFilters :配置排除扫描的规则,ANNOTATION-基于注解、ASSIGNABLE_TYPE-指定类型、CUSTOM-自定义规则

public class CustomFilterType implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //当前类的注解源信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //当前类class源信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //当前类资源信息
        Resource resource = metadataReader.getResource();
        System.out.println("类的路径:"+classMetadata.getClassName());
        if(classMetadata.getClassName().contains("dao")){
            return true;
        }
        return false;
    }
}

  includeFilters :配置扫描的包含规则。其中Filter配置去上面没有差别,但是注意,必须设置 useDefaultFilters = false ,否则默认是true,扫描全路径。

includeFilters = {
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {UserWoker.class})
        },useDefaultFilters = false

  2.3、Bean的作用域

    2.3.1、默认,在不指定@Scope的情况下,bean是单例的,并且是饿汉式加载,即容器启动的时候,就创建实例。
@Configuration
public class MainConfig {
    @Bean
    public Person person(){
        return new Person();
    }
}
     2.3.2、指定@Scope为 prototype 表示多实例,懒汉式加载,即容器启动的时候不会创建实例,在第一次使用的时候才会去创建。
@Configuration
public class MainConfig {
    /**
     *  Scope 配置bean作用域,默认单例模式:
     *      prototype - 多例模式,并且是懒汉式加载,在IOC容器启动的时候,不会创建对象,在第一次使用的时候才去创建
     *      singleton - 单例模式,默认饿汉式加载,在IOC启动的时候就创建对象
     */
    @Bean
    @Scope(scopeName = "prototype")
    public Person initPerson(){
        return new Person();
    }
}    
     2.3.3、@Scope 取值:singleton-单例(默认)、prototype-多实例、request-同一个请求、session-同一个会话

  2.4、懒加载

  懒加载@Lazy主要针对的是单例bean,容器启动的时候,不创建对象,第一次使用的时候才去创建。

@Configuration
public class MainConfig {

    /**
     *  Lazy 配置bean时候懒加载,与 Scope.singleton单例来配合上使用,容器启动的时候不创建对象,第一次使用的时候才去创建对象
     */
    @Bean
    @Lazy
    public Person initPerson(){
        return new Person();
    }
}

  2.5、@Conditional条件判断

  存在某个组件或者不存在某个组件的时候,才去加载或者不加载bean。Springboot体系中,大量使用到的机制,通常如 @ConditionalOnBean、@ConditionalOnClass 等。


    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        if(null != context.getBeanFactory().getBean(UserLog.class)){
            return true;
        }
        return false;
    }
}
@Configuration
public class MainConfig {

//    @Bean("userLog")
    public UserLog initUserLog(){
        return new UserLog();
    }

    /**
     * 当容器中有 userLog 组件的时候,才去实例化当前bean
     */
    @Bean
    @Conditional(value = {Userconditional.class})
//    @ConditionalOnBean(value = {UserLog.class})
    public UserAspect initUseraspect(){
        return new UserAspect();
    }
}

  2.6、IOC容器中添加组件的方法

    2.6.1、@ComponentScan + @Contoller @Service @Respository @Component, 自己写的组件,可以通过此种方式导入

    2.6.2、@Bean导入组件,适用于第三方组件的类

    2.6.3、@Import导入组件,导入的组件id为类名全路径。

@Configuration
@Import(value = {Person.class, Car.class, DogImportSelector.class, CatBeanDefiniitionRegister.class})
public class MainConfig {

}

public class DogImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.cfang.ioc.tImport.Dog"};
    }
}

public class CatBeanDefiniitionRegister implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //创建bean定义对象
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClass(Cat.class);
        //bean定义对象注册到容器中,并设置beanName
        registry.registerBeanDefinition("cat2", rootBeanDefinition);
    }
}

     2.6.4、通过FactoryBean注册组件

@Configuration
public class MainConfig {

    @Bean("personFactoryBean")
    public PersonFactoryBean initBean(){
        return new PersonFactoryBean();
    }
}

public class PersonFactoryBean implements FactoryBean<Person> {
    /**
     * 返回bean对象
     */
    @Override
    public Person getObject() throws Exception {
        return new Person();
    }
    /**
     * 设置bean类型
     */
    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }
    /**
     * 是否单例
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}

   2.7、Bean的初始化和销毁方法

    2.7.1、生命周期

      bean实例化创建 -----> 初始化 -------> use  -------->销毁方法。

      可通过指定bean的初始化init 和销毁destroy方法

@Configuration
@ComponentScan(value = {"com.cfang.ioc.lifecycle"})
public class MainConfig {
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
}

      单例bean,容器启动的是,bean就创建了,容器关闭的时候,也会调用对应的销毁bean方法。

      多例bean,容器启动的是,不创建,第一次使用的时候去创建,bean的销毁也不受IOC容器管理。

    2.7.2、实现 InitializingBean, DisposableBean

@Component
public class Book implements InitializingBean, DisposableBean {
    public Book(){
        System.out.println("Book构造方法...");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean.destory....");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean.afterPropertiesSet....");
    }
}

    2.7.3、@PostConstruct、@PreDestroy注解

@Component
public class Person {
    public Person(){
        System.out.println("Person构造方法...");
    }
    @PostConstruct
    public void init(){
        System.out.println("Person PostConstruct...");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("Person destroy...");
    }
}

     2.7.4、实现 BeanPostProcessor,bean后置处理器,可拦截bean创建过程

        postProcessBeforeInitialization - 在 init 方法之前调用

        postProcessAfterInitialization - 在 init 方法之后调用

@Component
public class TBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("TBeanPostProcessor.postProcessBeforeInitialization ..." + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("TBeanPostProcessor.postProcessAfterInitialization ..." + beanName);
        return bean;
    }
}

   2.8、属性主键赋值 @Value + @PropertySource

public class Person {

    @Value("商业")
    private String name;
    @Value("#{28-8}")
    private Integer year;
    @Value("${name}")
    private String lname;

    @Override
    public String toString() {
        return name + lname + year;
    }
}

@Configuration
@PropertySource(value = {"classpath:bean.properties"})
public class MainConfig {

    @Bean("person")
    public Person initBean(){
        return new Person();
    }
}

 

posted @ 2020-09-22 11:19  阿呆很呆非常呆  阅读(287)  评论(0编辑  收藏  举报