快捷搜索:  汽车  科技

spring源码深度解析和spring揭秘(1.Spring源码整体脉络及注解的使用)

spring源码深度解析和spring揭秘(1.Spring源码整体脉络及注解的使用)ORM: 如 JPA、Hibernate、iBatis 等,提供了 一个交互层。JDBC: 提供了一个 JDBC 抽象层,它可以消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 这个模块包含了 Spring 对 JDBC 数据访问进行封装的所有类。Context: (处理BeanFactory,以下还ApplicationContext的作用) 构建于 Core 和 beans 模块基础之上,提供了一种类似 JNDI 注册器的框架式的对象访问方法。 Context 模块继承了 Beans 的特性,为 Spring 核心提供了大量扩展,添加了对国际化(例如资源绑定)、事件传播、资源加载和对 Context 的透明创建的支持。Context 模块同时也支持 J2EE 的一些特性, ApplicationContext 接口是 Context。BeanFactory 和 Applactio

思维导图:点击查看思维导图
文章图片:点击查看图片

一、Spring框架功能整体介绍

spring源码深度解析和spring揭秘(1.Spring源码整体脉络及注解的使用)(1)

1.Spring Core Container

模块作用: Core 和 Beans 模块是框架的基础部分,提供 IOC(控制反转)和 DI (依赖注入) 特性。 这里的基础概念是 BeanFactory,它提供对 Factory 模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。

Core: 主要包含 Spring 框架基本的核心工具类, Spring 的其他组件都要用到这个包里的类,Core 模块是其他组件的基本核心。

Beans:(BeanFacotry的作用) 它包含访问配置文件、创建和管理 bean 以及进行 Inversion Of Control / Dependency Injection ( IOC/DI )操作相关的所有类。(思考题 1)

Context: (处理BeanFactory,以下还ApplicationContext的作用) 构建于 Core 和 beans 模块基础之上,提供了一种类似 JNDI 注册器的框架式的对象访问方法。 Context 模块继承了 Beans 的特性,为 Spring 核心提供了大量扩展,添加了对国际化(例如资源绑定)、事件传播、资源加载和对 Context 的透明创建的支持。Context 模块同时也支持 J2EE 的一些特性, ApplicationContext 接口是 Context。

BeanFactory 和 ApplactionContext 的区别: (思考题 2)

  • BeanFactory 是懒加载的,ApplactionContext 是非懒加载的(可以指定为懒加载)
  • BeanFactory 只有一个职责就是调用 getBean() 生产 Bean,而 ApplactionContext 是 BeanFactoy 的扩展,是面向用户的,有更多的实现(包括AOP、读取资源文件、国际化、事件传播等)

SPEL(Expression Language): 提供了强大的表达式语言,用于在运行时查询和操纵对象。

2.Spring Data Access/Integration

JDBC: 提供了一个 JDBC 抽象层,它可以消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 这个模块包含了 Spring 对 JDBC 数据访问进行封装的所有类。

ORM: 如 JPA、Hibernate、iBatis 等,提供了 一个交互层。

OXM: Object/XML 映射实现包括 JAXB、 Castor、 XMLBeans、 JiBX 和 XStrearn

JMS: 包含了 一些制造和消费消息的特性

Transaction: 支持编程和声明性的事务管理,这些事务类必须实现特定的接口,并且对所有的 POJO 都适用。

3.Spring Web

提供了基础的面向 Web 的集成特性。例如,多文件上传、使用 servlet listeners 初始化 IOC 容器以及一个面向 Web 的应用上下文。 它还包含 Spring 远程支持中 Web 的相关部分。

4.Spring Aop

Aspects: 提供了对 AspectJ 的集成支持。

Instrumentation: 提供了 class instrumentation 支持和 classLoader 实现,使得可以在特定的应用服务器上使用

5.Test

支持使用 JUnit 和 TestNG

二、Spring IOC 容器底层注解使用1.xml配置形式和配置类形式

①基于xml的形式定义Bean的信息

<bean class="com.zhe.spring.HelloSpring"> <property name="car" ref="car"/> </bean> <!-- 基于xml的形式定义Bean的信息 --> <bean id="car" class="com.zhe.spring.Car"></bean> 复制代码

// 1.基于xml的形式定义Bean的信息 // ClassPathXmlApplicationContext解析xml 去容器中读取Bean ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml"); log.debug(ctx.getBean("car").toString()); 复制代码

②基于读取配置类的形式定义Bean信息

@Configuration public class MainConfig { @Bean public Car car(){ return new Car(); } } 复制代码

// 2.基于读取配置类的形式定义Bean信息 // 通过@Bean的形式是使用的话, bean的默认名称是方法名,也可以通过@Bean(value="bean的名称") 指定 AnnotationConfigApplicationContext atx = new AnnotationConfigApplicationContext(MainConfig.class); log.debug(atx.getBean("car").toString()); 复制代码2.在配置类上写@CompentScan注解来进行包扫描

@Configuration @ComponentScan(basePackages = {"com.zhe.testcompentscan"}) public class MainConfig { } 复制代码

①排除用法 excludeFilters(排除@Controller注解的,和NotScanService的)

@Configuration @ComponentScan(basePackages = {"com.zhe.testcompentscan"} excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION value = {Controller.class}) @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE value = {NotScanService.class}) }) public class MainConfig { } 复制代码

②包含用法 includeFilters,注意,若使用包含的用法,需要把useDefaultFilters属性设置为false(true表示扫描全部的)

// 扫描Controller和Service @Configuration @ComponentScan(basePackages = {"com.zhe.testcompentscan"} includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION value = {Controller.class Service.class}) } useDefaultFilters = false) public class MainConfig { } 复制代码

public enum FilterType { //注解形式 比如@Controller @Service @Repository @Component ANNOTATION //指定的类型 ASSIGNABLE_TYPE //aspectJ形式的 ASPECTJ //正则表达式的 REGEX //自定义的 CUSTOM } 复制代码

③FilterType.CUSTOM 自定义类型如何使用

public class TestFilterType 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(); if(classMetadata.getClassName().contains("dao")) { return true; } return false; } 复制代码

@ComponentScan(basePackages = {"com.zhe.testcompentscan"} includeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM value = TestFilterType.class) } useDefaultFilters = false) public class MainConfig { } 复制代码3.配置Bean的作用域对象

①在不指定 @Scope 的情况下,所有的 bean 都是单例的 bean,而且是饿汉加载(容器启动实例就创建好了)

@Bean public Person person() { return new Person(); } 复制代码

②指定 @Scope 为 prototype 表示为多实例的,而且还是懒加载

@Bean @Scope(value = "prototype") public Person person() { return new Person(); } 复制代码

③@Scope 指定的作用域方法取值

a) singleton 单实例的(默认) b) prototype 多实例的 不能解决循环依赖 c) request 同一次请求复用一个单例对象 d) session 同一个会话级别复用一个单例对象 e) application ServletContext的生命周期中复用一个单例对象 f) websocket websocket的生命周期中复用一个对象 复制代码4.Bean的懒加载

@Lazy (主要针对单实例的 bean 容器启动的时候,不创建对象,在第一次使用的时候才会创建该对象)

@Bean @Lazy public Person person() { return new Person(); } 复制代码5.@Conditional 进行条件判断

场景: 有两个组件 TestAspect 和 TestLog,TestLog 组件是依赖于 TestAspect 的组件,当容器中有 TestAspect 时,TestLog 才会实例化

应用: 自己创建一个 TestCondition 的类实现 Condition 接口

public class TestCondition implements Condition { @Override public boolean matches(ConditionContext context AnnotatedTypeMetadata metadata) { //判断容器中是否有testAspect的组件 if(context.getBeanFactory().containsBean("testAspect")) { return true; } return false; } } 复制代码

public class MainConfig { @Bean public TestAspect testAspect() { return new TestAspect (); } //当且 容器中有testAspect的组件,那么testingLog才会被实例化. @Bean @Conditional(value = TestCondition.class) public TestLog testLog() { return new TestLog (); } } 复制代码6.往 IOC 容器中添加组件的方式6.1.通过 @CompentScan @Controller @Service @Respository @Component

适用场景: 针对我们自己写的组件可以通过该方式来进行加载到容器中

// 无论加哪个注解都是一样的,仅为提高可读性,推荐使用下面的方法 @Controller:控制器,推荐给controller层添加此注解 @Service:业务逻辑,推荐给业务逻辑层添加此注解 @Repository:仓库管理,推荐给数据访问层添加此注解 @Component:给不属于以上基层的组件添加此注解 复制代码

@Controller 是 @Component 的子组件

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { String value() default ""; } 复制代码6.2. 通过 @Bean 的方式来导入组件(适用于导入第三方组件的类)

@Bean是一个方法级别的注解,它与 XML中的元素类似。注解支持 提供的一些属性,例如 (init-method、destroy-method、autowiring、name ) 开发者可以在 @Configuration 类或 @Component 类中使用 @Bean 注解。

使用@Configuration注解类时,这个类的目的就是作为 bean 定义的地方。此外,@Configuration类允许通过调用同一个类中的其他@Bean方法来定义 bean 间依赖关系。

6.3.通过 @Import 来导入组件 (3 种方式,导入组件的id为全类名路径)

// @Import 注解允许从另一个配置类加载@Bean定义 @Configuration @Import(value = {Person.class Car.class}) public class MainConfig { } 复制代码

通过 @Import 的 ImportSeletor 类实现组件的导入 (导入组件的id为全类名路径)

public class TestImportSelector implements ImportSelector { //可以获取导入类的注解信息 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.zhe.testimport.compent.Dog"}; } } ​ @Configuration @Import(value = {Person.class Car.class TestImportSelector.class}) public class MainConfig { } 复制代码

通过 @Import 的 ImportBeanDefinitionRegister 导入组件 (可以指定 bean 的名称)

public class TestBeanDefinitionRegister implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata BeanDefinitionRegistry registry) { // 创建一个bean定义对象 rootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Cat.class); // 把bean定义对象导入到容器中 registry.registerBeanDefinition("car" rootBeanDefinition); } } ​ @Configuration // @Import(value = {Person.class Car.class}) // @Import(value = {Person.class Car.class TestImportSelector.class}) @Import(value = {Person.class Car.class TestImportSelector.class TestBeanDefinitionRegister.class}) public class MainConfig { ​ } 复制代码6.4.通过实现 FacotryBean 接口来实现注册组件(适合复杂初始化的Bean)

public class CarFactoryBean implements FactoryBean<Car> { //返回bean的对象 @Override public Car getObject() throws Exception { return new Car(); } //返回bean的类型 @Override public Class<?> getObjectType() { return Car.class; } //是否为单例 @Override public boolean isSingleton() { return true; } } 复制代码7.Bean的初始化方法和销毁方法

①什么是 Bean 的生命周期? bean的创建--->初始化--->销毁方法

由容器管理 Bean 的生命周期,我们可以通过自己指定 bean的 初始化方法和 bean 的销毁方法。

  • 针对单实例 bean 的话,容器启动的时候,bean 的对象就创建了(默认懒加载),而且容器销毁的时候,也会调用bean 的销毁方法
  • 针对多实例 bean 的话,容器启动的时候,bean 是不会被创建的而是在获取 bean 的时候被创建,而且 bean 的销毁不受 IOC 容器的管理

@Configuration public class MainConfig { //指定了bean的生命周期的初始化方法和销毁方法. @Bean(initMethod = "init" destroyMethod = "destroy") public Car car() { return new Car(); } public void init(){ // 初始化 } public void destroy(){ // 销毁 } } 复制代码

②通过 InitializingBean 和 DisposableBean 的二个接口实现 bean 的初始化以及销毁方法

@Component public class Person implements InitializingBean DisposableBean { public Person() { System.out.println("Person的构造方法"); } @Override public void destroy() throws Exception { System.out.println("DisposableBean的destroy()方法 "); } @Override public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean的 afterPropertiesSet方法"); } } 复制代码

③通过JSR250规范 提供的注解 @PostConstruct 和 @ProDestory 标注的方法

@Component public class Book { public Book() { System.out.println("book 的构造方法"); } @PostConstruct public void init() { System.out.println("book 的PostConstruct标志的方法"); } @PreDestroy public void destory() { System.out.println("book 的PreDestory标注的方法"); } } 复制代码

④通过 Spring 的 BeanPostProcessor 的 bean 的后置处理器会拦截所有 bean 创建过程执行顺序 Spring IOC 容器实例化 Bean => 调用BeanPostProcessor 的 postProcessBeforeInitialization 方法 => 调用 bean 实例的初始化方法 => 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法

  • postProcessBeforeInitialization 在 init 方法之前调用
  • postProcessAfterInitialization 在 init 方法之后调用

@Component public class TestBeanPostProcessor implements BeanPostProcessor { // init方法之前调用 @Override public Object postProcessBeforeInitialization(Object bean String beanName) throws BeansException { System.out.println("...postProcessBeforeInitialization:" beanName); return bean; } // init方法之后调用 @Override public Object postProcessAfterInitialization(Object bean String beanName) throws BeansException { System.out.println("...postProcessAfterInitialization:" beanName); return bean; } } 复制代码

BeanFactoryPostProcessor bean工厂的 bean 属性处理容器,用于管理我们的 Bean 工厂内所有的 Beandefinition(未实例化)数据,可以随心所欲的修改实例属性。

@Component public class TestMyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("TestMyBeanFactoryPostProcessor...postProcessBeanFactory..."); int count = beanFactory.getBeanDefinitionCount(); String[] names = beanFactory.getBeanDefinitionNames(); System.out.println("当前BeanFactory中有" count " 个Bean"); System.out.println(Arrays.asList(names)); } } 复制代码8.通过 @Value @PropertySource 来给组件赋值

public class Person { //通过普通的方式 @Value("值") private String firstName; //spel方式来赋值 @Value("#{38-8}") private Integer age; //通过读取外部配置文件的值 @Value("${person.lastName}") private String lastName; } @Configuration @PropertySource(value = {"classpath:person.properties"}) //指定外部文件的位置 public class MainConfig { @Bean public Person person() { return new Person(); } } 复制代码9.自动装配9.1.@Autowired的使用

自动注入:

//一个Dao @Repository public class TestDao { } @Service public class TestService { @Autowired private TestDao testDao; } 复制代码

注意:

  • 使用 @Autowired 注解时,自动装配的时候是根据类型实现的。
  • 1、如果只找到一个,则直接进行赋值,
  • 2、如果没有找到,则直接抛出异常,
  • 3、如果找到多个,那么会按照变量名作为 id 继续匹配
  • 1、匹配上直接进行装配
  • 2、如果匹配不上则直接报异常
  • 假设我们需要指定特定的组件来进行装配,我们可以通过使用@Qualifier("testDao")来指定装配的组件或者在配置类上的 @Bean 加上 @Primary 注解
  • 假设我们容器中没有 那么在装配的时候就会抛出异常 不抛异常就指定@Autowired(required = false)
  • /** * 当方法上有@AutoWired注解时: * 1、此方法在bean创建的时候会自动调用 * 2、这个方法的每一个参数都会自动注入值 * @param personDao */ @Autowired public void test(PersonDao personDao){ System.out.println("此方法被调用:" personDao); } ​ /** * @Qualifier注解也可以作用在属性上,用来被当作id去匹配容器中的对象,如果没有 * 此注解,那么直接按照类型进行匹配 * @param personService */ @Autowired public void test2(@Qualifier("personServiceExt") PersonService personService){ System.out.println("此方法被调用:" personService); } 复制代码
9.2.@Resource(JSR250规范)

功能和 @Autowired 的功能差不多一样,但是不支持 @Primary 和 @Qualifier。@Autowired只适合Spring 框架,而@Resource 扩展性更好。@Autowired 是 spring 中提供的注解,@Resource 是 JDK 中定义的注解,依靠的是 Java 的标准

9.3.@InJect(JSR330规范)

<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> 复制代码

需要导入jar包依赖。功能和支持@Primary功能 但是没有Require=false的功能

10.自己编写的组件需要使用 IOC 底层组件时(比如 ApplicationContext 等)可以通过实现XXXAware接口来实现

@Component public class TestCompent implements ApplicationContextAware BeanNameAware { private ApplicationContext applicationContext; @Override public void setBeanName(String name) { System.out.println("current bean name is :【" name "】"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } } 复制代码11.@Profile注解

通过@Profile注解来根据环境来激活标识不同的Bean

  • @Profile标识在类上,那么只有当前环境匹配,整个配置类才会生效
  • @Profile标识在Bean上 ,那么只有当前环境的Bean才会被激活
  • 没有标志为@Profile的bean 不管在什么环境都可以被激活

//标识为测试环境才会被装配 @Bean @Profile(value = "test") public DataSource testDs() { return buliderDataSource(new DruidDataSource()); } 复制代码

激活切换环境的方法:

// 方法一 -Dspring.profiles.active=test|dev|prod // 方法二 public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.getEnvironment().setActiveProfiles("test" "dev"); ctx.register(MainConfig.class); ctx.refresh(); printBeanName(ctx); } 复制代码三、Spring 源码的整体脉络

spring源码深度解析和spring揭秘(1.Spring源码整体脉络及注解的使用)(2)

1.控制反转和依赖注入

IOC容器的核心思想: 资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。

  • 资源集中管理,实现资源的可配置和易管理
  • 降低了使用资源双方的依赖程度,也就是我们说的耦合度(解耦)
  • 可维护性、灵活性、扩展性变高

控制反转(Inversion of control): (思考题 6) 创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的(new),而现在这种权力转移到第三方,比如转移交给了 IOC 容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖 IOC 容器了,通过 IOC 容器来建立它们之间的关系。

依赖注入(Dependency injection): 控制反转之后,获得依赖对象的过程由自身管理变为有 IOC 容器自动注入。依赖注入是实现 IOC 的方法,就是有 IOC 容器在运行期间,动态的将某种依赖关系注入到对象当中。

我们的类要生产成一个 Bean 不是一步到位的,它会涉及很多繁杂的步骤: (思考题3&4&5)

什么是 BeanDefinition 呢?

用来描述 Bean 的,存放关于 Bean 的一些列信息,例如:单例、多例、作用域、Bean对应的Class、是否懒加载等等。

spring源码深度解析和spring揭秘(1.Spring源码整体脉络及注解的使用)(3)

  • BeanDefinition 元数据信息,返回该 Bean 的来源
  • AttributeAccessor 提供对 BeanDefinition 属性操作能力

1.首先要将类加载成 BeanDefinition (Bean定义)

XML 配置的类可以读取成 Bean,Annotation (注解) 配置的类也可以读取 Bean 但是这两种 Bean 配置方式又不同 ,因此引申出统一的 Bean 定义:BeanDefinition

XML 和 Annotation 都会被先被读成 BeanDenfintion (里面包含了大量属性:限定类名、单例、多例等)。这个过程也包含一些列的复杂步骤:

  • a.读取配置类: BeanDefinitionReader 负责读取配置类,基于注解和 XML,又有 AnnotatedBeanDefinitionReader 、XmlBeanDefinitionReader读xml和Annotation 去读取各自的配置
  • b.扫描配置类: BeanDefinitionSacnner 负责扫描配置类 @Compontent。@Component 中可以添加有一些列的限制条件,BeanDefinitionSacnner 可以将符合条件的类读取到容器中,用于注册 BeanDenfintion
  • c.注册Bean定义: 最后由 BeanDefinitionRegistry 注册 BeanDenfintion 放入 BeanDefinitionMap 中

在这个过程中 ApplicationContext 还提供了扩展点来对 BeanDenfintion 进行扩展,Spring 生态除了 IOC 都需要这些扩展点来实现。它是 Spring 生态核心。如果我们需要集成使用很多其他框架(MyBatis、JPA等)都是通过这些扩展点去实现的。

修改 BeanDefinition 的扩展点

可以修改 BeanDefinition,只需要实现 BeanFactoryPostProcessor 接口,重写方法

  • postProcessBeanFactory BeanDefinition 的后置处理器,可修改Bean定义

添加 BeanDefinition 的扩展点

可以添加 BeanDefinition ,只需要实现 BeanDefinitionRegistryPostProcessor 重写方法

  • postProcessBeanDefinitionRegistry 注册 BeanDefinition,实现后会多注册 Bean

2.然后通过 BeanFactory 构造 Bean 存入一个 Map 中

通过 BeanFactory (简单工厂模式) 调用 getBean() 将 BeanDefinition 进行一些列的操作 (实例化、填充属性、初始化) 后将 Bean put 到一个 Map 中 (单例池缓存)。

  • a.实例化 (Instantiation)
  • 实例化后,此时还未自动装配,未生成 Bean 实体
  • b.填充属性 (Populate)
  • 在填充属性的过程中,可能会存在 A 引用了 B,B 又引用了 A 的情况,就可能产生循环依赖,Spring 为了解决这个问题引入了三级缓存 (三个 Map)
  • c.初始化 (Initialization)
  • 初始化的过程中还会调用一堆 Aware (初始化生命周期接口),最后将初始化好的 Bean put 到一个 Map<key value> 中去,这个Map是一个单例池缓存,实际就是一个 ConcurrentHashMap 保存起来,我们调用 getBean()就是从这个 Map 中拿
  • key :bean的名称,Value bean实例

实例化的两种方式:

  • 反射:Spring 自己控制 @Component 只会将类的 class 注入到 BeanDefinition 中
  • 工厂方法:更灵活,可以自己去new @Bean,里面可以自由控制 Bean 实例,new,赋值等

@Bean public Car car(){ return new Car(); } 复制代码

在调用 getBean() 过程中会涉及到九处后置处理器的调用,在创建时前后,实例化前后,填充属性前后,初始化前后等

① 实现 InstantiationAwareBeanPostProcessor

  • postProcessBeforelnstantiation 直接返回 Bean 停止后面的流程

② 实现 SmartInstantiationAwareBeanPostProcessor

  • determineCandidateConstructors 指定实例化构造函数

③ 实现 MergedBeanDefinitionPostProcessor

  • postProcessMergedBeanDefinition @AutoWired @Value 预解析

④ 实现 SmartInstantiationAwareBeanPostProcessor

  • getEarlyBeanReference 解决循环引用 AOP

⑤ 实现 InstantiationAwareBeanPostProcessor

  • postProcessAfterInstantiation 终止赋值

⑥ 实现 InstantiationAwareBeanPostProcessor

  • postProcessPropertyValues 注入属性PropertyValues @AutoWired 在这里进行依赖注入

⑦⑧ 实现 BeanPostProcess

  • postProcessBeforeInitialization 初始化前调用@PostConstruct
  • postProcessAfterInitialization 初始化后 AOP: 创建代理

⑨ DestructionAwareBeanPostProcessor

  • requiresDestruction

思考题:

1.描述 BeanFactory

2.BeanFactory 和 ApplicationContext 的区别?

3.简述 SpringIOC 的加载过程

4.简述 Bean 的生命周期

5.Spring 中有哪些扩展接口及调用时机

6.控制反转和依赖注入是什么


作者:Hz488
链接:https://juejin.cn/post/7127999778390016030

猜您喜欢: