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

一、Spring框架功能整体介绍

在这里插入图片描述

1.Spring Core Container

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

Core: 主要包含 Spring 框架基本的核心工具类, Spring 的其他组件都要用到这个包 里的类, Core 模块是其他组件的基 本核心。
Beans: (BeanFacotry的作用) 它包含访问配置文件、创建和管理 bean 以及进行 Inversion Of Control I 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的名称") 那么bean的名称是指定的
AnnotationConfigApplicationContext atx = new AnnotationConfigApplicationContext(MainConfig.class);
log.debug(atx.getBean("car1").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 @Compent 
	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 表示为多实例的,而且还是懒汉模式加载(IOC容器启动的时候,并不会创建对象,第一次使用的时候才会创建)

@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) { 
   //判断容器中是否有testingAspect的组件 
   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 来导入组件 (导入组件的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("TestBeanPostProcessor...postProcessBeforeInitialization:" + beanName); 
		return bean; 
	}
	// init方法之后调用
	@Override 
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("TestBeanPostProcessor...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));
    }
}

BeanPostProcessor的执行时机

populateBean(beanName, mbd, instanceWrapper) initializeBean{ 
	applyBeanPostProcessorsBeforeInitialization() 
	invokeInitMethods{
	 	isInitializingBean.afterPropertiesSet 
	 	//自定义的init方法 
	 }
	 applyBeanPostProcessorsAfterInitialization()方法 
}

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

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

  • 资源集中管理,实现资源的可配置和易管理

  • 降低了使用资源双方的依赖程度,也就是我们说的耦合度(解耦)

  • 可维护性、灵活性、扩展性变高

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

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

什么是 BeanDefinition 呢?

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

在这里插入图片描述

  • 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 停止后面的流程

② 实现 SmartInstantiationAwareBeanPostProcesso

  • determineCandidateConstructors 指定实例化构造函数

③ 实现 MergedBeanDefinitionPostProcessor

  • postProcessMergedBeanDefinition @AutoWired @Value 预解析

④ 实现 SmartInstantiationAwareBeanPostProcessor

  • getEarlyBeanReference 解决循环引用 AOP

⑤ 实现 InstantiationAwareBeanPostProcessor

  • postProcessAfterInstantiation 终止赋值

⑥ 实现 InstantiationAwareBeanPostProcessor

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

⑦⑧ 实现 BeanPostProcess

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

⑨ DestructionAwareBeanPostProcessor

  • requiresDestruction

思考题:

1.描述 BeanFactory

2.BeanFactory 和 ApplicationContext 的区别?

3.简述 SpringIOC 的加载过程

4.简述 Bean 的生命周期

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

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

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值