⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.im/post/6844903970658320391 「温安适」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

1. 从注解入手找到对应核心类

最近工作中我都是基于注解实现 AOP 功能,常用的开启 AOP 的注解是 @EnableAspectJAutoProxy,我们就从它入手。

上面的动图的流程的步骤就是: @EnableAspectJAutoProxy --> AspectJAutoProxyRegistrar -->AopConfigUtils .registerAspectJAnnotationAutoProxyCreatorIfNecessary -->AnnotationAwareAspectJAutoProxyCreator.class

AnnotationAwareAspectJAutoProxyCreator 查看其中文注释(如下),确定它就是 AOP 的核心类!-- 温安适 20191020

  1. AspectJAwareAdvisorAutoProxyCreator的子类 ,用于处理当前应用上下文中的注解切面
  2. 任何被AspectJ注解的类将自动被识别。
  3. 若SpringAOP代理模式可以识别,优先使用Spring代理模式。
  4. 它覆盖了方法执行连接点
  5. 如果使用aop:include元素, 则只有名称与include模式匹配的@aspectj bean才被视为切面 ,并由spring自动代理。
  6. Spring Advisors的处理请查阅,

org.springframework.aop
.framework.autoproxy.AbstractAdvisorAutoProxyCreator

@SuppressWarnings("serial")
public class AnnotationAwareAspectJAutoProxyCreator
extends AspectJAwareAdvisorAutoProxyCreator {
//...省略实现
}注解切面

虽然找到了核心类,但是并没有找到核心方法!下面我们尝试画类图确定核心方法。

2. 画核心类类图,猜测核心方法

AnnotationAwareAspectJAutoProxyCreator 的部分类图。

AnnotationAwareAspectJAutoProxyCreator 从类图看到了 AnnotationAwareAspectJAutoProxyCreator 实现了 BeanPostProcessor,而 AOP 功能应该在创建完 Bean 之后执行,猜测 AnnotationAwareAspectJAutoProxyCreator 实现 BeanPostProcessor 的 postProcessAfterInitialization(实例化 bean 后处理)是核心方法。查看 AnnotationAwareAspectJAutoProxyCreator 实现的 postProcessAfterInitialization 方法,实际该方法在其父类 AbstractAutoProxyCreator 中。

//AbstractAutoProxyCreator中的postProcessAfterInitialization实现
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

发现发现疑似方法 wrapIfNecessary,查看其源码如下,发现 createProxy 方法。确定找对了地方。

protected Object wrapIfNecessary
(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass())
|| shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// 创建代理
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;
}

this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

即 AnnotationAwareAspectJAutoProxyCreator 实现 BeanPostProcessor 的 postProcessAfterInitialization 方法,在该方法中由 wrapIfNecessary 实现了 AOP 的功能。wrapIfNecessary 中有 2 个和核心方法

  • getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器
  • createProxy 为当前 bean 创建代理 要想明白核心流程还需要分析这 2 个方法。

3. 读重点方法,理核心流程

3.1 getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器

查看源码如下,默认实现在 AbstractAdvisorAutoProxyCreator 中。

@Override
@Nullable
protected Object\[\] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName,
@Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO\_NOT\_PROXY;
}
return advisors.toArray();
}

查阅 findEligibleAdvisors 方法,就干了 3 件事

  • 找所有增强器,也就是所有 @Aspect 注解的 Bean
  • 找匹配的增强器,也就是根据 @Before,@After 等注解上的表达式,与当前 bean 进行匹配,暴露匹配上的。
  • 对匹配的增强器进行扩展和排序,就是按照 @Order 或者 PriorityOrdered 的 getOrder 的数据值进行排序,越小的越靠前。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//找所有增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//找所有匹配的增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

AnnotationAwareAspectJAutoProxyCreator 重写了 findCandidateAdvisors,下面我们看看具体实现了什么

3.1.1findCandidateAdvisors 找所有增强器,也就是所有 @Aspect 注解的 Bean

@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
//@Aspect注解的类在这里除了
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}

从该方法我们可以看到处理 @Aspect 注解的 bean 的方法是:this.aspectJAdvisorsBuilder.buildAspectJAdvisors()。这个方法如下:

public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;

if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//找到所有BeanName
String\[\] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// 必须注意,bean会提前暴露,并被Spring容器缓存,但是这时还不能织入。
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
//找到所有被@Aspect注解的类
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析封装为Advisor返回
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}

if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}

这个方法可以概括为:

  • 找到所有 BeanName
  • 根据 BeanName 筛选出被 @Aspect 注解的类
  • 针对类中被 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 注解的方法,先按上边的注解顺序排序后按方法名称排序,每一个方法对应一个 Advisor。

3.2 createProxy 为当前 bean 创建代理。

3.2.1 创建代理的 2 种方式

众所周知,创建代理的常用的 2 种方式是:JDK 创建和 CGLIB,下面我们就看看这 2 中创建代理的例子。

3.2.1 .1 jdk 创建代理的例子

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxyMain {

public static void main(String\[\] args) {
JDKProxyTestInterface target = new JDKProxyTestInterfaceImpl();
// 根据目标对象创建代理对象
JDKProxyTestInterface proxy =
(JDKProxyTestInterface) Proxy
.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new JDKProxyTestInvocationHandler(target));
// 调用代理对象方法
proxy.testProxy();
}

interface JDKProxyTestInterface {
void testProxy();
}
static class JDKProxyTestInterfaceImpl
implements JDKProxyTestInterface {
@Override
public void testProxy() {
System.out.println("testProxy");
}
}
static class JDKProxyTestInvocationHandler
implements InvocationHandler {
private Object target;
public JDKProxyTestInvocationHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method,
Object\[\] args) throws Throwable {
System.out.println("执行前");
Object result= method.invoke(this.target,args);
System.out.println("执行后");
return result;
}
}

3.2.1 .2 cglib 创建代理的例子

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyTest {

static class CglibProxyService {
public CglibProxyService(){
}
void sayHello(){
System.out.println(" hello !");
}
}

static class CglibProxyInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object sub, Method method,
Object\[\] objects, MethodProxy methodProxy)
throws Throwable {
System.out.println("before hello");
Object object = methodProxy.invokeSuper(sub, objects);
System.out.println("after hello");
return object;
}
}

public static void main(String\[\] args) {
// 通过CGLIB动态代理获取代理对象的过程
Enhancer enhancer = new Enhancer();
// 设置enhancer对象的父类
enhancer.setSuperclass(CglibProxyService.class);
// 设置enhancer的回调对象
enhancer.setCallback(new CglibProxyInterceptor());
// 创建代理对象
CglibProxyService proxy= (CglibProxyService)enhancer.create();
System.out.println(CglibProxyService.class);
System.out.println(proxy.getClass());
// 通过代理对象调用目标方法
proxy.sayHello();
}
}

3.2.1 .3 jdk 创建代理与 cglib 创建代理的区别

3.2.2 Spring 如何选择的使用哪种方式

Spring 的选择选择如何代理时在 DefaultAopProxyFactory 中。

public class DefaultAopProxyFactory implements AopProxyFactory,
Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config)
throws AopConfigException {
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.");
}
if (targetClass.isInterface()
|| Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
//...
}

  • config.isOptimize() 查看源码注释时发现,这个是配置使用 cglib 代理时,是否使用积极策略。这个值一般不建议使用!
  • config.isProxyTargetClass() 就是 @EnableAspectJAutoProxy 中的 proxyTargetClass 属性。

//exposeProxy=true AopContext 可以访问,proxyTargetClass=true CGLIB 生成代理 @EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)

  • hasNoUserSuppliedProxyInterfaces 是否存在可代理的接口

总结下 Spring 如何选择创建代理的方式:

  1. 如果设置了 proxyTargetClass=true,一定是 CGLIB 代理
  2. 如果 proxyTargetClass=false,目标对象实现了接口,走 JDK 代理
  3. 如果没有实现接口,走 CGLIB 代理

4. 总结

Spring 如何实现 AOP?,您可以这样说:

  1. AnnotationAwareAspectJAutoProxyCreator 是 AOP 核心处理类
  2. AnnotationAwareAspectJAutoProxyCreator 实现了 BeanProcessor,其中 postProcessAfterInitialization 是核心方法。
  3. 核心实现分为 2 步 getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器 createProxy 为当前 bean 创建代理
  4. getAdvicesAndAdvisorsForBean 核心逻辑如下 a. 找所有增强器,也就是所有 @Aspect 注解的 Bean b. 找匹配的增强器,也就是根据 @Before,@After 等注解上的表达式,与当前 bean 进行匹配,暴露匹配上的。 c. 对匹配的增强器进行扩展和排序,就是按照 @Order 或者 PriorityOrdered 的 getOrder 的数据值进行排序,越小的越靠前。
  5. createProxy 有 2 种创建方法,JDK 代理或 CGLIB a. 如果设置了 proxyTargetClass=true,一定是 CGLIB 代理 b. 如果 proxyTargetClass=false,目标对象实现了接口,走 JDK 代理 c. 如果没有实现接口,走 CGLIB 代理
文章目录
  1. 1. 1. 从注解入手找到对应核心类
  2. 2. 2. 画核心类类图,猜测核心方法
  3. 3. 3. 读重点方法,理核心流程
    1. 3.1. 3.1 getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器
      1. 3.1.1. 3.1.1findCandidateAdvisors 找所有增强器,也就是所有 @Aspect 注解的 Bean
    2. 3.2. 3.2 createProxy 为当前 bean 创建代理。
      1. 3.2.1. 3.2.1 创建代理的 2 种方式
        1. 3.2.1.1. 3.2.1 .1 jdk 创建代理的例子
        2. 3.2.1.2. 3.2.1 .2 cglib 创建代理的例子
        3. 3.2.1.3. 3.2.1 .3 jdk 创建代理与 cglib 创建代理的区别
      2. 3.2.2. 3.2.2 Spring 如何选择的使用哪种方式
  4. 4. 4. 总结