Java进阶-Spring-IOC

一、IOC

1.1 延迟查找

  SpringFramework 4.3 中引入了一个新的 API :ObjectProvider,可以实现延迟查找

ApplicationContext context = new ClassPathXmlApplicationContext("context/beanDefine.xml");
ObjectProvider dogProvider = context.getBeanProvider(Person.class);
Person person = dogProvider.getIfAvailable(Person::new);

https://www.jianshu.com/p/27ced9a9854d

  使用场景:

  • 可以让依赖的资源充分等到初始化完成之后再使用
  • 可以和@Lazy注解配合充分实现延迟初始化
  • 可用于解决构造器级别的循环依赖

1.2 @Autowired的注入原理

  先拿属性对应的类型,去 IOC 容器中找 Bean ,如果找到了一个,直接返回;如果找到多个类型一样的Bean,把属性名拿过去,跟这些 Bean 的 id 逐个对比,如果有一个相同的,直接返回;如果没有任何相同的 id 与要注入的属性名相同,则会抛出 NoUniqueBeanDefinitionException 异常。

1.3 @Autowired和@Resource区别

  • 构造器注入/setter注入

  • @Autowired 按类型注入, 可指定required=false来避免注入失败

  • @Resource 按名称注入,相当于@Autowired+@Qualifier

1.4 回调注入

  ApplicationContextAware、BeanNameAware 接口。

  • 当ApplicationContext创建了一个实现ApplicationContextAware接口的对象实例时,就为该实例提供了ApplicationContext引用
  • 当ApplicationContext创建实现BeanNameAware接口的类时,该类提供了在其关联对象定义中定义的名称的引用

https://www.cnblogs.com/springmorning/p/10355859.html

1.5 FactoryBean

  ApplicationContext初始化Bean的时机默认是容器加载时就已经创建,FactoryBean本身的加载是伴随 IOC 容器的初始化时机一起的。FactoryBean生产Bean的机制是延迟生产

  • BeanFactory :SpringFramework 中实现IOC的最底层容器(此处的回答可以从两种角度出发:从类的继承结构上看,它是最顶级的接口,也就是最顶层的容器实现;从类的组合结构上看,它则是最深层次的容器,ApplicationContext在最底层组合了BeanFactory)
  • FactoryBean :创建对象的工厂Bean,可以使用它来直接创建一些初始化流程比较复杂的对象。
  • FactoryBean的生命周期与IOC容器一致,而FactoryBean生产bean的时机是延迟创建的。

1.6 Bean生命周期

image.png

  在IOC容器初始化之前,默认情况下Bean已经创建好了,而且完成了初始化动作;容器调用销毁动作时,先销毁所有Bean,最后IOC容器全部销毁完成

  Bean的生命周期中,是先对属性赋值,后执行init-method标记的方法。

  • init-method & destroy-method
  • @PostConstruct & @PreDestroy
  • InitializingBean & DisposableBean
image.png
image.png

https://juejin.cn/post/7075168883744718856

1.7 BeanFactory

image.png
  • HierarchicalBeanFactory
  • ListableBeanFactory
image.png
  • AutowireCapableBeanFactory
  • ConfigurableBeanFactory
  • AbstractBeanFactory(getBeanDefinition/createBean)
  • AbstractAutowireCapableBeanFactory
  • DefaultListableBeanFactory

1.8 ApplicationContext

image.png
  • AbstractApplicationContext - refresh
image.png

1.9 模块装配

模块

  • 独立的
  • 功能高内聚
  • 可相互依赖
  • 目标明确

模块装配:把一个模块需要的核心功能组件都装配好
核心原则:自定义注解 + @Import 导入组件

@Import

  • 导入普通类
  • 导入ImportSelector接口实现类
  • 导入ImportBeanDefinitionRegistrar实现类

https://blog.csdn.net/Howinfun/article/details/118932670

1.10 条件装配

  • @Profile
      默认default
      基于环境的配置:根据当前项目的运行时环境不同,可以动态的注册当前运行环境匹配的组件。

  • @Conditional

  被@Conditional注解标注的组件,只有所有指定条件都匹配时,才有资格注册。条件是可以在要注册BeanDefinition之前以编程式确定的任何状态

  实现Condition接口-条件匹配规则类

https://blog.csdn.net/weixin_46535927/article/details/119387476

1.11 组件扫描

  include的过滤规则之间互相不受影响,且不会互相排除;排除型过滤器会排除掉其他过滤规则已经包含进来的Bean

1.12 资源管理

image.png
  • ProtocolResolver
  • DefaultResourceLoader
  • @PropertySource
  • PropertySourceFactory
  • DefaultPropertySourceFactory

1.13 Environment抽象

image.png
  • Environment中包含profiles和properties,这些配置信息会影响IOC容器中的bean的注册与创建;
  • Environment的创建是在ApplicationContext创建后才创建的,所以Environment应该是伴随着ApplicationContext的存在而存在
  • ApplicationContext中同时包含Environment和组件bean ,而且从BeanFactory的视角来看,Environment 也是一个Bean,只不过它的地位比较特殊。
image.png

1.14 BeanDefinition & BeanDefinitionRegistry

  BeanDefinition描述了一个bean的实例,该实例具有属性值,构造函数参数值以及具体实现所提供的更多信息。这只是一个最小的接口,它的主要目的是允许BeanFactoryPostProcessor(例如 PropertyPlaceholderConfigurer )内省和修改属性值和其他bean的元数据。

  BeanDefinition描述了SpringFramework中bean的元信息,它包含bean的类信息、属性、行为、依赖关系、配置信息等。BeanDefinition具有层次性,并且可以在IOC容器初始化阶段被BeanDefinitionRegistryPostProcessor构造和注册,被BeanFactoryPostProcessor拦截修改等。

image.png
  • BeanDefinition继承了AttributeAccessor 接口,具有配置bean属性的功能;

  BeanDefinitionRegistry是维护BeanDefinition的注册中心,它内部存放了 IOC 容器中bean的定义信息,同时BeanDefinitionRegistry也是支撑其它组件和动态注册Bean的重要组件。在SpringFramework中,BeanDefinitionRegistry的实现是DefaultListableBeanFactory。

  • BeanFactoryPostProcessor,可实现去除beanDefinition
  • BeanDefinition的合并

1.15 后置处理器

  BeanPostProcessor是一个回调机制的扩展点,它的核心工作点是在bean的初始化前后做一些额外的处理(预初始化bean的属性值、注入特定的依赖,甚至扩展生成代理对象等)。

  • BeanPostProcessor的执行可以指定先后顺序,实现Ordered接口;
  • BeanPostProcessor作用于bean对象的创建后,不同IOC容器中的BeanPostProcessor不会互相起作用
  • BeanPostProcessor提供了两个回调时机:bean的初始化之前和bean的初始化之后,它们分别适合做填充和代理的工作;
image.png
  • postProcessBeforeInitialization是用来填充的,而工厂就是做的这事。如果使用FactoryBean就是说用户已经把想填充的内容在工厂里做好了,spring不应该再插手,所以不会调用postProcessBeforeInitialization。
image.png
  • InstantiationAwareBeanPostProcessor
  • SmartInstantiationAwareBeanPostProcessor
  • DestructionAwareBeanPostProcessor
  • MergedBeanDefinitionPostProcessor

1.16 BeanFactoryPostProcessor

image.png

  BeanFactoryPostProcessor是容器的扩展点,它用于IOC容器的生命周期中,所有BeanDefinition都注册到BeanFactory后回调触发,用于访问/修改已经存在的BeanDefinition。与BeanPostProcessor相同,它们都是容器隔离的,不同容器中的BeanFactoryPostProcessor不会相互起作用。

image.png

1.17 BeanDefinitionRegistryPostProcessor

image.png

  BeanDefinitionRegistryPostProcessor是容器的扩展点,它用于 IOC 容器的生命周期中,所有BeanDefinition都准备好,即将加载到BeanFactory时回调触发,用于给BeanFactory中添加新的BeanDefinition。BeanDefinitionRegistryPostProcessor也是容器隔离的,不同容器中的BeanDefinitionRegistryPostProcessor不会相互起作用。

  BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry执行完毕后,会先执行它们的postProcessBeanFactory,然后才能轮到普通的BeanFactoryPostProcessor执行。

image.png

spring-BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor、BeanPostProcessor三者区别

1.18 编程式驱动IOC

  refresh方法的执行,会触发非延迟加载的单实例bean的实例化和初始化。

  使用模块装配,通过标注一个@EnableJdbc的注解,能够根据当前工程中导入的数据库连接驱动,注册对应的数据源到IOC容器。

  SPI:通过一种服务寻找的机制,动态的加载接口/抽象类对应的具体实现类。它把接口具体实现类的定义和声明权交给了外部化的配置文件中。SpringFramework 中的SPI相比较于jdk原生的,不仅仅局限于接口/抽象类,它可以是任何一个类、接口、注解。

https://github.com/just-right/spring-study

1.19 事件&监听器

  子容器的事件会向上传播到父容器,父容器的事件不会向下传播

  • ApplicationEvent/ApplicationListener/PayloadApplicationEvent/

  ApplicationEventPublisher和ApplicationEventMulticaster,它们分别代表事件发布器和事件广播器。事件发布器是用来接受事件,并交给事件广播器处理;事件广播器拿到事件发布器的事件,并广播给监听器

1.20 Bean生命周期-补充

  • BeanDefinition部分
    • BeanDefinition的解析
    • BeanDefinition的注册
  • bean实例部分
    • bean的实例化
    • bean的属性赋值+依赖注入
    • bean的初始化流程
    • bean的启动与停止
    • bean的销毁
image.png

  BeanPostProcessor的扩展InstantiationAwareBeanPostProcessor可以在bean的实例化之后、初始化之前执行postProcessAfterInstantiation方法,以及postProcessProperties( postProcessPropertyValues) 方法完成属性赋值。BeanPostProcessor的回调包含bean的初始化之前和初始化之后,但DestructionAwareBeanPostProcessor只包含bean销毁回调之前的动作,没有之后。

  首先ClassPathXmlApplicationContext在refresh之前,会指定传入的xml配置文件的路径,执行refresh方法时,会初始化BeanFactory,触发xml配置文件的读取、加载和解析。其中xml的读取需要借助XmlBeanDefinitionReader ,解析xml配置文件则使用 DefaultBeanDefinitionDocumentReader ,最终解析xml中的元素,封装出BeanDefinition,最后注册到 BeanDefinitionRegistry。

  注解配置类的解析发生在BeanDefinitionRegistryPostProcessor的执行阶段,它对应的核心后置处理器是ConfigurationClassPostProcessor ,它主要负责两个步骤三件事情:解析配置类、注册BeanDefinition。三件事情包括:1) 解析@ComponentScan 并进行包扫描,实际进行包扫描的组件是ClassPathBeanDefinitionScanner ;2) 解析配置类中的注解(如 @Import 、@ImportResource 、@PropertySource 等)并处理,工作的核心组件是ConfigurationClassParser ;3) 解析配置类中的 @Bean并封装BeanDefinition,实际解析的组件是ConfigurationClassBeanDefinitionReader。

image.png
image.png
image.png

1.21 参考链接

https://www.jianshu.com/p/1dec08d290c1
https://juejin.cn/book/6857911863016390663/section/6867492434910117902
https://juejin.cn/post/6956814839729618957

你可能感兴趣的:(Java进阶-Spring-IOC)