likes
comments
collection
share

1.Spring源码整体脉络及注解的使用

作者站长头像
站长
· 阅读数 53

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

一、Spring框架功能整体介绍

1.Spring源码整体脉络及注解的使用

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 源码的整体脉络

1.Spring源码整体脉络及注解的使用

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、是否懒加载等等。

1.Spring源码整体脉络及注解的使用

  • 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.控制反转和依赖注入是什么

\

转载自:https://juejin.cn/post/7127999778390016030
评论
请登录