学成路更宽,吊打面试官。 ——小马哥
大家好,我是小马哥成千上万粉丝中的一员!2019年8月有幸在叩丁狼教育举办的猿圈活动中知道有这么一位大咖,从此结下了不解之缘!此系列在多次学习极客时间《小马哥讲Spring AOP 编程思想》基础上形成的个人一些总结。希望能帮助各位小伙伴, 祝小伙伴早日学有所成。
从命名可知这个抽象类主要功能就是自动创建代理,怎么实现自动?这就得与 Spring IoC 容器打通。所以此抽象类实现了
SmartInstantiationAwareBeanPostProcessor
和BeanFactoryAware
BeanPostProcessor
实现,在调用 bean 本身之前将委托给指定的拦截器。公共的
拦截器(为它创建的所有代理共享)以及 特定的
拦截器(每个 bean 实例都是唯一的)。如果有公共的
拦截器,则使用 interceptorNames
属性设置它们(与 ProxyFactoryBean 一样,使用当前工厂中的拦截器名称而不是 bean 引用来允许正确处理原型 advisor 和拦截器)getAdvicesAndAdvisorsForBean
方法)来决定一个 bean 是否要被代理,例如根据类型、名称、定义细节等。它们还可以返回应该只应用于特定 bean 实例的额外拦截器。一个简单的具体实现是 BeanNameAutoProxyCreator,它通过给定的名称标识要代理的 bean。TargetSourceCreator
实现都可以用于创建自定义目标源:例如,将原型对象池化。即使没有 advice,只要 TargetSourceCreator 指定了自定义 TargetSource,也会发生自动代理。如果没有设置 TargetSourceCreators ,或者没有匹配的,默认情况下将使用 SingletonTargetSource 来包装目标 bean 实例。标记接口,用于识别 Spring AOP 基础结构一部分的 bean,避免当 Pointcut 匹配时生成代理对象。
用于创建代理时配置的便利超类,以确保所有代理创建器具有一致的属性。
主要配置:
false
使用 JDK 基于接口的动态代理false
。例如,优化通常意味着在创建代理之后通知更改不会生效。因此,优化在默认情况下是禁用的。如果其他设置排除了优化,那么“true”的优化值可能会被忽略;例如,如果 exposeProxy
被设置为 true
,而这与优化不兼容。false
,任何 AOP 代理都可以强制转换为 Advised
。Advice
更改。这对于优化很有用,当我们不希望调用方能够在强制转换为 Adviced
后操作配置时也很有用。具有代理处理器通用功能的基类,特别是 ClassLoader 管理和 evaluateProxyInterfaces 算法。
通过属性 boolean classLoaderConfigured 管理属性 proxyClassLoader 只允许设置一次
检查给定 bean 类上的接口,并将它们应用到 ProxyFactory(如果可用的话)。调用 isConfigurationCallbackInterface(Class>) 和 sInternalLanguageInterface(Class>) 来过滤合理的代理接口。如果没有可用接口则使用 CGLIB 代理。
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 获取类中的所有接口,如果是接口返回它自己
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
/**
* 获取的接口列表,只要接口列表满足一个不是 Spring 框架 InitializingBean、DisposableBean、Aware 接口扩展接口和
* 不是 Jdk 中 AutoCloseable 和 Closeable 接口并且不是内部语言接口(接口名称是 groovy.lang.GroovyObject
* 或者是以 .cglib.proxy.Factory 结尾或者 .bytebuddy.MockAccess 结尾)并且不是空接口
*/
for (Class<?> ifc : targetInterfaces) {
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
// 如果有可代理的接口添加到代理工厂中
if (hasReasonableProxyInterface) {
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
// 没有接口就设置 CGLIB 代理
proxyFactory.setProxyTargetClass(true);
}
}
实现 setBeanFactory((BeanFactory beanFactory) 方法。并且该实现类交由 Spring IoC 管理。则由 Spring IoC 容器在填充普通 bean 属性之后,但在初始化回调(如 iinitializingBean.afterPropertiesSet() 或自定义初始化方法之前调用。
Bean 的后置处理器,可以通过实现此接口覆写 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法对 bean 进行修改,比如 AbstractAutoProxyCreato 就是通过覆写 postProcessAfterInitialization 返回代理对象
BeanPostProcessor
的子接口,它添加了一个实例化之前的回调函数和一个实例化之后但在显式属性设置或自动装配发生之前的回调函数。通常用于抑制特定目标 bean 的默认实例化,例如创建带有特殊 targetsource 的代理(池化目标、延迟初始化目标等),或者实现额外的注入策略,如字段注入。
此接口扩展了 InstantiationAwareBeanPostProcessor接口,添加一个 predictBeanType 回调,用于预测已处理 bean 的最终类型。
通过委派已配置的 Aop 代理接口,创建实际的代理对象。Spring AOP 通过
DefaultAopProxyFactory
提供了开箱即用 的 JDK 动态代理(JdkDynamicAopProxy) 和 CGLIB 代理(ObjenesisCglibAopProxy)
getProxy
方法获取代理对象(默认的 ClassLoader)ClassLoader
的 getProxy(@Nullable ClassLoader classLoader)
方法获取代理对象基于
AdvisedSupport
配置对象新增 AOP 代理的工厂接口
代理应该遵守以下契约:
Advised
接口equals
方法用于比较代理接口、advice 和 目标对象唯一实现:DefaultAopProxyFactory#createAopProxy(AdvisedSupport config) 方法分析
AopProxyFactory 默认实现,创建不是 JDK 动态代理就是 CGLIB 代理。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
/**
* 对于给定的 AdvisedSupport 实例,如果满足以下任意条件,则创建一个 CGLIB 代理:
* 1. 优化标志被设置
* 2. proxyTargetClass 标志被设置(即使设置了如果被代理对象是接口还是使用 JDK 动态代理)
* 3. 没有指定代理接口
*/
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 目标对象是接口或者是已经被 JDK 动态代理代理过的对象则创建 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
advisorAdapterRegistry
属性管理 AdvisorAdapterRegistry 默认是 GlobalAdvisorAdapterRegistry
(DefaultAdvisorAdapterRegistry),在前面 AbstractAutoProxyCreator 功能介绍最后一条中介绍即使没有
Advice
,只要TargetSourceCreator
指定了自定义TargetSource
,也会发生自动代理,将会在postProcessBeforeInstantiation
介绍
interceptorNames
属性管理公共拦截器setInterceptorNames(String... interceptorNames)
方法进行设置setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst)
方法设置公共拦截器与特殊拦截的先后顺序由于 AbstractAutoProxyCreator 实现了 BeanFactoryAware 便于底层 IoC 打通,具有依赖查找的能力
@Override
@Nullable
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
// 如果代理类型缓存为空则跳过
if (this.proxyTypes.isEmpty()) {
return null;
}
/**
* 如果 bean 名称为空则 cacheKey 则是类对象;
* 如果有 bean 类型是 FactoryBean 则 cacheKey 则是 &beanName;
* 否则 cacheKey 就是 beanName
*/
Object cacheKey = getCacheKey(beanClass, beanName);
// 通过 cacheKey 去代理类型缓存获取
return this.proxyTypes.get(cacheKey);
}
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
/**
* 如果 bean 名称为空把 bean Class 对象作为 cacheKey ;
* 如果有 bean 类型是 FactoryBean 则 cacheKey 则是 &beanName;
* 否则 cacheKey 就是 beanName
*/
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 缓存早期代理引用
this.earlyProxyReferences.put(cacheKey, bean);
// 根据条件生成代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果通过了自定义 TargetSourceCreator 方式处理过目标实例则不需要代理
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 内部基础 bean 或者不需要代理的 bean 则不代理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/**
* 是否是基础设施(默认规则 Advice、Pointcut、Advisor、AopInfrastructureBean)
* 或者不需要进行代理(默认规则是否是类名与 bean 名称长度必须相同并且 bean 名称以类名开头以 .ORIGINAL)则不代理。并放入 advisedBeans 缓存中
*/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { // 方入 advisedBean 缓存以便重复创建 bean 时提供性能
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 根据子类实现不同的规则获取 Advice/Advisor.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 满足生成代理对象条件
if (specificInterceptors != DO_NOT_PROXY) {
// 放入缓存
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 生成代理对象(子类可覆写)
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 放入代理类型缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 如果没有符合条件的 advice 则不生成代理并缓存
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
/**
* 获取 beanName 的 BeanDefinition 并设置一个
* 属性名为 org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass 值为 beanClass 属性
*/
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 通过 ProxyFactory 来创建代理对象
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 使用 JDK 动态代理
if (!proxyFactory.isProxyTargetClass()) {
/**
* 通过 beanName 的 BeanDefinition 获取属性名
* org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass.preserveTargetClass
* 的属性值是否为 true 如果是 true 即使 proxyFactory.isProxyTargetClass() 是 false 还是会使用 CGLIB 动态代理
*/
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 父类 ProxyProcessorSupport#evaluateProxyInterfaces 方法在上面已经分析过了
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 构建 Advisor(后面分析)
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
// 空方法留给子类扩展
customizeProxyFactory(proxyFactory);
// 是否冻结代理对象(默认是 false)
proxyFactory.setFrozen(this.freezeProxy);
// 是否对 Advisor 预过滤(默认是 false 留给子类扩展 AbstractAdvisorAutoProxyCreator 是 true)
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 通过代理工厂根据 ClassLoader 获取代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
确定给定 bean 的 Advisor,包括特定的拦截器和公共拦截器,然后把这些拦截器都适配成 Advisor 对象。
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
/**
* 根据内部关联 BeanFactory 通过 IoC 根据公共的拦截器的 bean 名称获取 bean
* 然后再通过内部关联的 DefaultAdvisorAdapterRegistry 包装成类型为`DefaultPointcutAdvisor` 的 Advisor
*/
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
// 特定的拦截器不为空再根据是否设置了公共拦截器在前,合并这些拦截器
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 通过内部关联的 DefaultAdvisorAdapterRegistry 把拦截器包装成 Advisor
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
自动构建
Advisor
代理列表,子类覆写findCandidateAdvisors()
获取Advisor
列表。也可以通过覆写AbstractAutoProxyCreator.shouldSkip(java.lang.Class>, java.lang.String)
方法跳过自动代理。 通过 @Order 注解或者实现 Ordered 接口来控制 Adivosr/Advice。通过AnnotationAwareOrderComparator
来排序 Advisor/Advice。没有 @Order 注释或没有实现 Ordered 接口的 Advisor 将被认为是无序的;它们将以未定义的顺序出现在 Advisor 链的末尾。
实现 AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean 方法,委派给本类 findEligibleAdvisors() 方法(子类可以覆写)
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 委派给 findEligibleAdvisors() 方法(子类可以覆写)
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 通过 IoC 容器获取所有 Advisor 实例
List<Advisor> candidateAdvisors = findCandidateAdvisors();
/**
* 如果 Advisor 类型是 IntroductionAdvisor 获取关联的 ClassFilter 进行匹配
* 如果 Advisor 类型是 PointcutAdvisor 获取关联的 ClassFilter 进行匹配,如果匹配成功再获取 MethodMatcher 进行静态匹配(2个参数 matches() 方法 )
*/
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 扩展接口子类实现
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
AbstractAdvisorAutoProxyCreator 子类,它暴露 AspectJ 的调用上下文,并在多个 advice 来自相同的 aspect 时推断 AspectJ 的 advice 优先级规则(AspectJPrecedenceComparator 比较器)。
ExposeInvocationInterceptor
把 MethodInvocation
暴露到上下文,以便在 AspectJ 中操作(例如 AbstractAspectJAdvice#currentJoinPoint 方法和 AspectJExpressionPointcut#matches(Method method, Class> targetClass, Object… args) 方法)PartiallyComparableAdvisorHolder
中关联的AnnotationAwareOrderComparator
进行排序AspectJAwareAdvisorAutoProxyCreator 子类,它处理当前应用上下文用中所有的 AspectJ 中 @Aspect 注解 以及 Spring Advisor ,通过 ReflectiveAspectJAdvisorFactory 和 BeanFactoryAspectJAdvisorsBuilderAdapter 相互搭配实现
@Override
protected List<Advisor> findCandidateAdvisors() {
// 通过 Spring IoC 容器获取所有 Advisor Bean
List<Advisor> advisors = super.findCandidateAdvisors();
// 通过 Spring IoC 容器获取所有标注 @AspectJ 注解的 Bean,再获取标注 AspectJ 注解(除了@Pointcut 其他的注解 @After、@Before、@AfterReturning 等)的方法
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
自动代理创建主要利用 Spring IoC 的 BeanPostProcessor#postProcessAfterInitialization
方法进行扩展,再利用 getAdvicesAndAdvisorsForBean
模板方法根据不同规则获取 Advice/Advisor(比如 Bean 名称,Bean 类型以及 AspectJ ),然后由 ProxyFactory
委派给 DefaultAopProxyFactory
(默认,也可以替换)获取代理对象