一、Spring 框架基础原理篇

1.框架整体脉络

  • 1.创建容器
  • 2.加载配置文件,解析成beanDefinition
  • 3.初始化beanFactoryPostProcessor,调用beanFactoryPostProcessor
  • 4.初始化beanPostProcessor
  • 5.实例化bean
  • 6.初始化bean
    • 6.1填充属性
    • 6.2调用aware接口
    • 6.3调用beanPostProcessor的before方法
    • 6.4调用init-method
    • 6.5调用beanPostProcessor的after方法
  • 7.程序中使用bean
  • 8.销毁bean

2.加载BeanDefinition

加载beanDefinition有两种方式,一种是xml形式,一种是注解,xml形式通过Resource加载器加载,DOM解析,封装成BeanDefinition,注册到beanDefinitionMap;注解方式依赖于@ComponentScan注解,该注解上配置了包扫描路径,启动过程中,后置处理器ConfigurationClassPostProcessor调用了处理方法,创建ClassPathBeanDefinitionScanner,调用doScan方法,这里是@ComponentScan的实质性逻辑,从配置的包路径下获取所有的类,遍历出符合过滤条件的类,默认是带有@Component注解的,然后注册到beanDefinitionMap中

3.bean工厂后置处理器 beanFactoryPostProcessor

bean工厂后置处理器,spring的扩展点,可以自定义类实现BeanFactoryPostProcessor接口,该接口的实现方法中能拿到beanFactory,进而实现对beanFactory的修改定制。后置处理器的创建和调用在refresh()里面的invokeBeanFactoryPostProcessors(beanFactory)

4.bean后置处理器 BeanPostProcessor

bean后置处理器,spring的扩展点,可以自定义类实现BeanPostProcessor接口,该接口有两个实现方法,一个是初始化前,一个是初始化后,可以对bean进行修改。后置处理器的创建在refresh()里面的registerBeanPostProcessors(beanFactory),调用则是在finishBeanFactoryInitialization(beanFactory),即普通单例bean创建的过程中org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

4.1 InstantiationAwareBeanPostProcessor

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor

在bean初始化前后做一些事情
在这里插入图片描述

5.bean初始化接口 InitializingBean

6.public interface FactoryBean

7.AOP原理

  • 使用
  1. 启动类上标注@EnableAspectJAutoProxy开启aop
package com.example.aop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class AopApplication {

    public static void main(String[] args) {
        SpringApplication.run(AopApplication.class, args);
    }

}

  1. 编写切面类,@Aspect 标注,定义切点,编写增强方法
package com.example.aop.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class UserAspect {

    @Pointcut("execution(* com.example.aop.service..*(..))")
    public void pointcut(){}

    @Before("pointcut()")
    public void before(){
        System.out.println("before..");
    }
}

  • 原理
  1. @EnableAspectJAutoProxy --> @Import(AspectJAutoProxyRegistrar.class)
    在这里插入图片描述

  2. AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar --> AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); --> return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    在这里插入图片描述
    在这里插入图片描述

  3. 可以看到,引入了AnnotationAwareAspectJAutoProxyCreator,一个bean后置处理器
    在这里插入图片描述

  4. AbstractAutoProxyCreator的父类实现了InstantiationAwareBeanPostProcessor接口,在bean实例化before方法里面实现了切面的解析逻辑
    在这里插入图片描述
    org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors,这个方法遍历所有的beanName,从beanFactory拿到bean信息,判断有没有@Aspect注解,有说明是切面,进行解析,将其转化成Advisor
    在这里插入图片描述
    在这里插入图片描述

  5. 解析完切面之后就是创建代理了,创建代理发生在初始化After方法org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
    在这里插入图片描述
    获取bean的匹配的advisor,然后创建代理,配置了proxy-target-class="true"使用cglib,没有没有配置且有接口则使用jdk动态代理

8.@Transaction原理

9.@Import原理

https://blog.csdn.net/gongsenlin341/article/details/113281596

  • @Import 提供与Spring XML中的<import/>元素等价的功能。
    允许导入@Configuration配置类,ImportSelector
    ImportBeanDefinitionRegistrar实现类,以及常规组件
    类别(截至4.2; 类似于AnnotationConfigApplicationContext#register)。
  • org.springframework.context.annotation.ConfigurationClassParser#processImports
    该注解标注在普通类上,这个普通类会被配置类后置处理器ConfigurationClassPostProcessor(默认创建)处理@ComponentScan的时候封装(普通类标注了下图四种注解会被当成配置类处理)成配置类ConfigurationClass,然后当成配置类处理,最终把@Import引入的类注册到beanDefinitionMap中;假如注解标注在配置类上,则直接在配置类的processImports中处理;强调一下,普通类的处理会被包装成配置类进行处理,ImportSelector里面的类经过递归也会调用普通类的处理方法
    在这里插入图片描述

9.1ImportSelector 、ImportBeanDefinitionRegistrar

public interface ImportSelector {

	/**
	 * Select and return the names of which class(es) should be imported based on
	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
	 * @return the class names, or an empty array if none
	 * 
	 * 基于导入的配置类的注解元数据来选择并返回那些需要导入的类的名称
	 * 返回那些类名,如果没有则返回空数组
	 * 这个地方如果返回的是ImportSelector ,貌似会死循环哦
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);

	/**
	 * Return a predicate for excluding classes from the import candidates, to be
	 * transitively applied to all classes found through this selector's imports.
	 * <p>If this predicate returns {@code true} for a given fully-qualified
	 * class name, said class will not be considered as an imported configuration
	 * class, bypassing class file loading as well as metadata introspection.
	 * @return the filter predicate for fully-qualified candidate class names
	 * of transitively imported configuration classes, or {@code null} if none
	 * @since 5.2.4
	 * 
	 * 返回一个断言,用于从导入候选对象中排除类
	 */
	@Nullable
	default Predicate<String> getExclusionFilter() {
		return null;
	}

}

@Import(ImportSelector.class)相当于在@Import(普通类)的基础上做了增强,通过接口返回数组允许导入多个类,然后通过断言又可以对导入的类进行过滤

public interface ImportBeanDefinitionRegistrar {

	/**
	 * Register bean definitions as necessary based on the given annotation metadata of
	 * the importing {@code @Configuration} class.
	 * 
	 * 根据需要基于导入的配置类的注解元数据注册bean 的定义
	 */
	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
			BeanNameGenerator importBeanNameGenerator) {

		registerBeanDefinitions(importingClassMetadata, registry);
	}

	/**
	 * Register bean definitions as necessary based on the given annotation metadata of
	 * the importing {@code @Configuration} class.
	 */
	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	}

}

@Import(ImportBeanDefinitionRegistrar .class)可以更灵活的注册BeanDefinition,因为ImportBeanDefinitionRegistrar 接口的两个方法参数可以直接拿到registry。但是此种方式的逻辑调用跟前两种有点差别,这是在所有的配置类(@Configuration修饰的和包装的配置类)解析成ConfigurationClass之后,执行配置类的加载bean定义方法里面执行的;而之前提到的两种配置类的解析过程中执行的。
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars

10.@Autowired原理

https://blog.csdn.net/hc1428090104/article/details/124823573

  • 创建bean的方法doCreateBean
  • 调用填充属性方法populateBean(beanName, mbd, instanceWrapper)
  • 调用Autowired后置处理器(各个后置处理器循环调用)org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
  • postProcessProperties方法首先查找需要注入的成员,然后执行注入方法,通过反射调用java.lang.reflect.Field#set注入;在set前会先处理好依赖,没有则调doCreateBean 创建resolveFieldValue(field, bean, beanName);

11.监听器listenner

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值