• Spring的IOC常用注解(含源码)


    一、容器中注入组件

    1,包扫描 + 组件标注注解

      源码:Demo01_ComponentScan

    a)组件标注

    • @Controller
    • @Service
    • @Repository
    • @Component

    b)包扫描@ComponentScan

      @ComponentScan中主要值的解释

    • value:扫描的包路径(数组)
    • excludeFilters:指定扫描的时候按照什么规则排除那些组件(@ComponentScan.Filter)includeFilters:指定扫描的时候只需要包含哪些组件。使用同excludeFilter。
      • FilterType.ANNOTATION:按照注解
      • FilterType.ASSIGNABLE_TYPE:按照给定的类型
      • FilterType.ASPECTJ:使用ASPECTJ表达式
      • FilterType.REGEX:使用正则指定
      • FilterType.CUSTOM:使用自定义规则
    • useDefaultFilters:是否使用默认的扫描机制。默认按照a)中组件标注扫描

    2,使用@Bean导入

    a)@Scope作用域

    • prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
    • singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿,
    • request:同一次请求创建一个实例
    • session:同一个session创建一个实例

    b)@Lazy

      单实例bean:默认在容器启动的时候创建对象;

      懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化。

    c)@Conditional

      @Bean上加改注解,按照一定的条件进行判断,满足条件给容器中注册bean;如在类上加改注解,这个类中配置的所有bean注册才能生效。

    • @ConditionalOnClass 表示如果有后面的类,那么就加载这个自动配置;
    • @ConditionalOnMissingClass 如果没有后面的类,才自动配置。如果没有就配置,保证bean的唯一。

      大量运用于SpringBoot中。

    3,使用@Import导入

      源码:Demo02_Import

      快速为容器中导入一个组件。

    • @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
    • ImportSelector:返回需要导入的组件的全类名数组
    • ImportBeanDefinitionRegistrar:手动注册bean到容器中。1.new RootBeanDefinition(Dog.class);2.registry.registerBeanDefinition()。

    4,FactoryBean(工厂Bean)

      源码:Demo03_FactoryBean

      将实现FactoryBean的类加到容器中。

    • 默认从容器中获取到的是工厂bean调用getObject创建的对象。
    • 要获取工厂Bean本身,我们需要给id前面加一个&

    二、Bean的生命周期

    1,bean生命周期

      bean创建 --- 初始化 --- 销毁

    • 构造(对象创建)
      • 单实例:在容器启动的时候创建对象
      • 多实例:在每次获取的时候创建对象
    • 初始化:
      • 成员变量赋值,各种增强等,对象创建完成,并赋值好,调用初始化方法
    • 销毁:
      • 单实例:容器关闭的时候
      • 多实例:容器不会管理这个bean;容器不会调用销毁方法;

    2,定义Bean初始化和销毁

    a)定义initMethod和destroyMethod

      源码:Demo04_BeanLifeCycleCar

    • 定义初始化方法,定义@Bean的initMethod为该方法
    • 定义销毁方法,定义@Bean的destroyMethod为该方法

    b)实现InitializingBean和DisposableBean接口

      源码:Demo04_BeanLifeCycleDog

    • 定义当前对象实现InitializingBean接口。其中afterPropertiesSet方法会在当前对象设置完属性之后调用。
    • 定义当前对象实现DisposableBean接口。其中destroy方法会在当前对象销毁的时候调用。

    c)可以使用JSR250

      源码:Demo04_BeanLifeCycleColor

    • @PostConstruct定义在方法上,则该方法会在Bean创建并且属性赋值之后执行,为初始化方法
    • @PreDestroy定义在方法上,则该方法在容器销毁bean之前通知我们进行清理工作

    d)实现BeanPostProcessor,bean的后置处理

      源码:Demo04_BeanLifeCycleDemo04_BeanPostProccessor

      在bean初始化前后进行一些处理工作;

    • postProcessBeforeInitialization:在初始化之前工作
    • postProcessAfterInitialization:在初始化之后工作

    3,从源码看BeanPostProcessor后置处理器

      在Spring类AbstractAutowireCapableBeanFactory中方法doCreateBean可以看到

    //给bean进行属性赋值
    populateBean(beanName, mbd, instanceWrapper);
    //初始化bean
    exposedObject = initializeBean(beanName, exposedObject, mbd);

      在方法initializeBean中可以看到

    //调用applyBeanPostProcessorsBeforeInitialization进行初始化之前的处理
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    //调用自定义初始化方法
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }catch ...//调用applyBeanPostProcessorsAfterInitialization进行初始化之后的处理
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    总结:

      BeanPostProcessor会在Bean对象创建并属性赋值完成之后,在执行init初始化方法的前后进行增加

    4,BeanPostProcessor在Spring中的应用

    a)ApplicationContextAware各种Aware接口

      查看源码类ApplicationContextAwareProcessor实现了BeanPostProcessor接口,其中postProcessBeforeInitialization的实现为:

    //如果当前bean为各种指定的Aware的bean就会执行invokeAwareInterfaces方法
    this.invokeAwareInterfaces(bean);
    
    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            ...
            //如果当前bean为ApplicationContextAware的子类,则会调用其setApplicationContext将applicationContext进行赋值
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
            }
        }
    }

      所以在ApplicationContextAware时,可以通过setApplicationContext获取到ApplicationContext上下文对象

    b)BeanValidationPostProcessor

      查看BeanValidationPostProcessor实现了BeanPostProcessor接口,其中不管是postProcessBeforeInitialization还是postProcessAfterInitialization,均调用了doValidate方法来验证当前bean是否合理

    c)@PostConstruct和@PreDestroy方法

      查看InitDestroyAnnotationBeanPostProcessor实现了BeanPostProcessor接口,其中postProcessBeforeInitialization在当前bean初始化之前的源码为:

    //获取生命周期的metadata,得到标注有@PostConstruct和@PreDestroy的方法
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        //这个方法会采用反射的方式,调用方法
        metadata.invokeInitMethods(bean, beanName);
    }...

    d)AutowiredAnnotationBeanPostProcessor

      用来处理@Autowire注解的属性

    三、属性赋值

    • @Value:给属性赋值,也可以使用SpEL和外部文件的值
    • @PropertySource:读取外部配置文件中的k/v保存到运行环境中。@PropertySource(value={"classpath:/application.yaml"})
    • @Autowried 装配优先级如下:构造器、参数、方法、属性。
      • 使用按照类型去容器中找对应的组件
      • 如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
    • @Qualifier:使用@Qualifier指定需要装配的组件的id,结合@Autowried使用
    • @Primary:spring自动装配的时候,默认首先bean,配合@Bean使用
    • @Resource(JSR250):jsr规范:按照组件名称进行装配,不支持@Primary和@Autowired(reqiured=false)
    • @Inject(JSR330):jsr规范和@Autowired功能一致,不支持require=false;
    • @Profile:结合@Bean使用,默认为default环境,可以通过命令行参数来切换环境
      • 加上VM参数:-Dspring.profiles.active=dev 则采用的dev环境。多个用逗号隔开
      • 1.无参构造ApplicationContext,2.通过applicationContext.getEnvironment().setActiveProfiles("dev"),3.注册配置类applicationContext.register(Main.class),4.采用ApplicationContext.refresh()
  • 相关阅读:
    运算符重载
    简单函数template max
    const static extern
    python 关闭垃圾回收
    Easy and cheap cluster building on AWS backup
    [转] Maven更新父子模块的版本号, mvn versions:set
    [转] ansible批量执行命令展示
    HBase 批量删除表 disable_all drop_all
    自动添加 ssh key 到远程主机的脚本,应用sshpass和ssh-copy-id
    MongoDB ver 4 几个常用命令
  • 原文地址:https://www.cnblogs.com/bbgs-xc/p/14494185.html
Copyright © 2020-2023  润新知