Spring笔记

Spring Bean 生命周期

接口:
BeanDefinition: Spring Framework 中定义 Bean 的配置元信息接口
GenericBeanDefinition: BeanDefinition的实现类
BeanDefinitionRegistry:往spring容器中注册BeanDefinition。

实例化与初始化的区别:
实例化是构造函数调用;初始化是设置属性;

初始化相回调接口 :
初始化前:BeanPostProcessor.postProcessBeforeInitialization
初始化:InitializingBean.afterPropertiesSet()
初始化后:BeanPostProcessor.postProcessAfterInitialization

Spring Resource

接口:
Resource:抽象底层资源的访问
ResourceLoader:用来加载 Resource 对象;ApplicationContext都实现了该接口。
ResourceLoaderAware: 回调扩展接口,给Bean提供ResourceLoader的能力。

Resource 实现:
UrlResource
FileUrlResource
FileSystemResource
ClassPathResource
ByteArrayResource

上下文:
ClassPathXmlApplicationContext、FileSystemXmlApplicationContext
使用:
引用的模板资源路径没有前缀时,使用跟上下文类型一样的前缀,取决于上下文的确切类型。

Spring IOC

IOC Inversion of Control 的缩写,即控制反转;
ID Dependency Injection ,是IOC的具体描述;

IoC 容器:具有依赖注入功能的容器。
IoC 容器负责 配置bean元数据、实例化、及建立这些对象间的依赖。以及使用容器(获取bean)。
有两种 IoC 容器:BeanFactory 和 ApplicationContext。

在程序中使用bean:
@Resource(name = "flower")
或者
@Autowired
@Qualifier("dog")
或者
Inject

Spring Aop 面向方面编程

AOP是对OOP在程序结构角度的补充。
OOP模块的部件是类,AOP模块的部件是方面。
方面可以使关注点模块横切多个类型和对象,例如事务管理方面。

AOP框架是Spring框架的一个关键组件。Spring IOC容器不依赖AOP。AOP 补充了 Spring IoC ,共同提供非常强大的Spring中间件解决方案。

在Spring框架中,Spring AOP有两种使用方式:一是声明式,比如声明式事务,儿是用户实现的方面,用AOP来补充OOP。

Aop概念

Aspect:方面。是对跨多个类的关注点的模块化。在Spring AOP中,通常用@AspectJ风格的@Aspect 注解标注。

Join point: 连接点。在程序执行期间的一个点,例如方法执行或者异常处理。在Spring AOP中,连接点总是表示方法执行。

Advice: 通知。在特定的连接点上被方面执行的操作。通知类型包括,环绕、前置和后置。许多AOP框架,包括Spring AOP框架,会把通知实现为拦截器,围绕一个通知会有一串拦截器链。

Pointcut:切入点。匹配一组连接点的判定。通知与切入点表达式关联,并且运行在切入点表达式匹配的一组连接点上。AOP的核心就是被切入点表达式匹配的那些连接点。Spring 默认使用 AspectJ 切入点表达式语言。

Target object: 目标对象。被方面通知的对象。由于Spring通过动态代理实现AOP,所以在Spring AOP中,目标对象总是被代理对象。

AOP proxy: AOP 代理。 AOP框架创建的一个对象,实现通知方法的执行。Spring框架有JDK动态代理和Cglib动态代理两种。

Weaving: 编织。把方面与应用程序类型或对象链接在一起创建通知对象。可以在编译,加载,运行时执行编织。Spring AOP在运行时实现编织。

类图


参考: https://programming.vip/docs/how-spring-aop-generates-proxy-objects.html

类图分为四部分:
1、代理配置信息:中间靠右部分,以AdvisedSupport为代表,上有代理信息类ProxyConfig,上有代理创建入口。
2、代理创建部分:最右侧部分,AopPorxyFactory为入口,传入配置信息。根据配置选择两种ProxyFactory。
3、切点部分:最左侧部分,类过滤器和方法过滤器。以PointCut为顶级接口。
4、通知部分:中间靠左部分,以Advice为核心。
其中还有一部分,连接点Joinpoint ,方法参数信息,图上没有显示。

ProxyCreatorSupport: 子类有ProxyFactoryBean和ProxyFactory。
ProxyFactory:编程用于AOP代理的工厂,不能用在bean factory内的声明式设置。这个类提供了一种简单的用户自定义代码获取和配置Aop代理方法。
ProxyFactoryBean:

使用 ProxyFactoryBean 创建AOP代理

FactoryBean 引入了一个间接层,以创建不同类型的对象。

在Spring中,创建AOP代理的基本方式是使用ProxyFactoryBean。这种方式可以完全控制切入点,通知和通知执行顺序,如果不想完全控制,还有更简单的选择。

ProxyFactoryBean 的getObject()方法可以创建一个包装目标对象的Aop代理。
使用ProxyFactoryBean或者可编织IOC容器的类创建AOP代理的好处之一,通知和切入点也可以被IOC管理。

ProxyFactoryBean 也是一个JavaBean,有两个属性,指定想代理的目标,指定是否用CGLIB。
有一些关键的属性是从ProxyConfig 继承的,这个类是Spring中所有AOP proxy factories的超类。
ProxyConfig的属性有,
proxyTargetClass:boolean类型,表示是否是类或者接口,如果是类使用Cglib代理;
optimize: 针对Cglib的优化,Jdk代理此参数无效。
frozen:代理配置是否被冻结,被冻结时,不允许调用者通过通知操作代理。默认是false。
exposeProxy: 通过ThreadLocal将代理暴露给目标类。目标类可以用AopContext.currentProxy()方法获取代理。

具体指定到ProxyFactoryBean的属性包括:
proxyInterfaces:一组字符串类型的接口名数组,如果没有指定,使用Cglib进行代理。
interceptorNames:通知拦截器或者其它通知的字符串类型数组。是有顺序的,列表中的第一个被首先执行。这些名称是当前工厂中的 bean 名称,还可以使用*符号添加拦截器名。
singleton: boolean类型,工厂是否返回单例值。false时使用prototype模式的bean。

Spring 工作流程

参考:
Spring容器启动流程

Spring 生态

Spring Jpa

JpaRepositoryFactoryBean:

JpaRepositoryFactory & RepositoryFactorySupport :
实现以下功能
1、生成repository接口的实例:创建实例,增加实例的代理方法。
2、getRepository获取代理类方法:内部使用AOP ProxyFactory 类生成实例。
3、实例的代理方法使用ProxyFactory 的通知来存放的。

RepositoryFactoryBeanSupport

RepositoryProxyPostProcessor:
postProcess(ProxyFactory factory, RepositoryInformation repositoryInformation)
repository proxy创建时的回调方法,在回调逻辑中可以加入一些通知,被代理的方法调用时

参考:
Spring Data JPA 工作原理 : 自定义JpaRespository接口却不用提供实现

循环依赖

Bean构造时,互相依赖,A->B,B->A。
一般是由构造函数注入引起。

解决:
除了重新设计Bean之外,引入第三方,可以通过以下方式解决。
1、@Lazy
@Lazy 和 @Autowired或@Inject 一起使用。
在初始化当前Bean时,被以上注解修饰的Bean会有懒加载,被注入Bean使用一个动态代理类注入,不会实际初始化,直到使用时才会初始化。

2、Setter/Field 注入:Bean定义无参构造函数,对另外Bean的引入Autowired定义到set方法或者field上。
容器在初始化的时候,先通过无参构造函数,把所有Bean初始化,然后再互相注入已有Bean。

3、@PostConstruct
4、Implement ApplicationContextAware and InitializingBean

参考:https://www.baeldung.com/circular-dependencies-in-spring

容器扩展点 BeanPostProcessor & BeanFactoryPostProcessor & FactoryBean

通常我们不需要继承ApplicationContext,而是通过插入特殊接口的实现来扩展 Spring IoC 容器。

BeanPostProcessor

在Spring 容器完成实例、配置和初始化Bean之后,可以加入一个或者多个BeanPostProcessor实现,实现Order接口可以按照顺序执行。

一些 Spring AOP 基础类被实现为 bean 后处理器,用来提供代理包装逻辑。

BeanPostProcessor 也是Bean,ApplicationContext 会自动检测实现 BeanPostProcessor 接口的Bean。

BeanPostProcessor 要提前于普通Bean 被初始化,因为这些BeanPostProcessor 要作用于普通Bean的初始化。

使用程序增加 BeanPostProcessor: ConfigurableBeanFactory 的 addBeanPostProcessor 方法。程序增加是忽略Order的,但是顺序是在ApplicationContext检测到的BeanPostProcessor之前的。

BeanFactoryPostProcessor

接口语义跟BeanPostProcessor相似,主要不同是,BeanFactoryPostProcessor 在Bean配置元数据上操作。

可以支持多个BeanFactoryPostProcessor 实例,实现Order接口可以按照顺序执行。

是Bean工长后处理器。

FactoryBean

是 Spring IoC 容器实例化逻辑的可插入点。

在FactoryBean中,相比XML配置文件,可以表达复杂的初始化逻辑,

FactoryBean 概念用在了Spring框架大量的地方,有50多处实现。

getBean("&myBean") 返回FactoryBean实例本身,getBean("myBean")返回被FactoryBean的制品。

参考
Container Extension Points
Spring内置的BeanPostProcessor总结 spring-embedded-bean-post-processor
spring-aop

posted on 2022-02-15 17:29  千里小马  阅读(98)  评论(0)    收藏  举报

导航