注解操作实现IOC内置Bean的各种操作

Annotation

组件注册导进IOC容器

  • @bean

    • @Conditional

    按照条件进行装配bean的操作

    代码实现

    自定义一个类完成自定义条件,自定义类继承Condition类,实现方法

    在配置类的装配方法加上注解@Condition(MyCondition.class)

  • @Configuration:注册配置类-(相当于配置文件)

  • 包扫描+组件注解()ComponentScan/@Controller/@Service/@Repository/@Component

  • @Import

  1. 在配置类上加上@import(导入的组件)能快速导入组件(自动注册),id默认是全类名

  2. ImportSelector:返回需要导入的组件全类名数组

    通过自定义类继承ImportSelector并实现方法完成自定义导入装配bean

    @Import(MyImportSelector.class)即可,ImportSelector内没有返回则会将自身装配进IOC容器

  3. ImportBeanDefinitionRegistry:手动注册bean到容器

  • Spring提供的FactoryBean
  1. 默认获取到的是工厂bean调用的getObject创建的对象
  2. 获取工厂bean本身需要在id前面加前缀&

Springboot含有大量自动配置,其实依靠它们@Configuration,@Import,@Conditional

管理bean生命周期

生命周期:创建 -> 初始化 -> 销毁的过程

Spring允许我们自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候调用我们自定义的初始化和销毁方法

初始化和销毁什么时候执行?

初始化:

​ 对象创建完成并赋值后,调用初始化方法

销毁:

单实例bean在容器关闭时自动销毁

多实例bean,容器不会调用bean的销毁方法

  1. 指定初始化和销毁

    • init-methoddestroy-method
      • @Bean(initMethod="方法名", destroyMethod="方法名")指定方法
  2. 通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑)

    • 组件类继承InitializingBean, DisposableBean,实现其初始化,销毁方法
  3. 使用JSR250规范(Java的一种规范)

    • @PostConstruct标注在初始化方法上
    • @PostDestroy标注在销毁方法上
  4. BeanPostProcessor - bean的后置处理器

    是对bean初始化前后进行的一些处理

    实现BeanPostProcessor接口来自定义后置处理器

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

    底层原理:

    首先在Bean初始化方法invokeInitMethods(beanName, wrappedBean, mbd)执行初始化前,先执行applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)来for循环其所有BeanPostProcessor,并执行其BeanPostProcessorBeforeInitialization方法,返回null则直接结束循环返回结果,不会执行之后的BeanPostProcessor。同理于applyBeanPostProcessorsAfterInitialization

    大致流程:

    • populateBean(beanName, mbd, instanceWrapper);-> 给bean属性赋值
    • initializeBean
      • applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
      • invokeInitMethods(beanName, wrappedBean, mbd)->执行初始化
      • applyBeanPostProcessorsAfterInitialization

    Spring当中的BeanPostProcesso实现类有哪些?(挑局部的来讲)

    • AutowiredAnnotationBeanPostProcessor -> 自动注入组件注解的实现,来对bean进行赋值(容器中含有则找到这个singleton bean)
    • initDestroyAnnotationBeanPostProcessor -> 找到控制生命周期的注解方法,利用反射调用
    • MethodValidationPostProcessor -> bean赋值校验
    • @Async等等xxBeanPostProcessor

属性赋值

@Value

  1. 赋基本数值 -> @value("基本数值")
  2. Spring表达式(SpEL - Spring Expression Language)-> #{}
  3. 读取配置文件 - 运行在环境变量中 -> ${}
    • 可以使用@PropertySource(value={"路径如:classpath:/xxx.properties"})读取配置文件中的Key-Value保存到运行时环境变量中

自动装配

Spring使用依赖注入(DI)来对IOC容器中各个组件的依赖关系赋值

Spring支持以下常用注解开发,都是由AutowiredAnnotationBeanPostProcessor解析完成自动装配的功能

  • @Autowired

    • 默认优先按照类型在容器中寻找对于的组件
    • 有多个相同类型的组件,将按照组件名称的id去找
    • 可以使用@Qualifier("")指定需要装配的组件id
    • 默认要赋值,找不到就会报错(设置@Autowired(required=false)则可以为null)
    • @Primary给某个bean设置为默认首选装配对象,@Qualifier也生效

    可以在构造器,参数,方法,属性上标注@Autowired,凡在参数或方法或构造器,都是将其参数从容器拿

    注意:如果组件只有一个有参构造器,这个有参构造器@Autowired可省略,该参数默认从容器中获取

  • @Resource ->(JSR250) [Java规范的注解]和@Inject ->(JSR330) [Java规范的注解]

    • @Resource
      • 跟@Autowired相同效果,id默认赋值组件名称
      • 不支持@Primary,和没有require的属性
    • @Inject
      • 需要导包javax.inject,也没有require属性
  • ...等等

  • Aware接口:把Spring底层的组件注入自定义的Bean

在自定义组件想使用Spring容器底层的一些组件如ApplicationContext,BeanFactory,xxx等,可以自定义组件实现xxxAware接口(xxxAware继承自Aware接口),调用接口方法来注入相关组件。

xxxAware的功能也是使用xxxProcessor继承BeanPostProessor来实现的

ApplicationContextAware -->ApplicationContextAwareProcessor

底层实现流程是

​ 调用ApplicationContextAwareProcessorPostProcessorBeforeInitialization方法,该方法内先判断bean是否继承自xxxAware接口,有则判断AccessControlContext是否赋值,有值则进入doPrivileged方法执行权限检查判断是否有权限访问,AccessControlContext为null则调用私有方法invokeAwareInterface(bean)来判断继承自哪一个xxxAware接口并将相应的组件注入进来(本例子是ApplicationContext)

简单来说就是:

  1. 本组件bean在初始化之前调用后置处理器ApplicationContextAwareProcessorPostProcessorBeforeInitialization方法
  2. 判断该bean继承自那个xxxAware组件(本例是ApplicationContextAware)`
  3. 将此xxxAware对应的Spring容器底层组件调用setxxx方法注入进bean(本例是setApplicationContext(ApplicationContext context))

  • @Profile

按照环境条件选择注入bean

posted @ 2020-10-27 21:25  Faink  阅读(171)  评论(0)    收藏  举报