Spring的AOP底层解析(springaop底层实现原理)

  本篇文章为你整理了Spring的AOP底层解析(springaop底层实现原理)的详细内容,包含有spring aop底层原理实现流程 springaop底层实现原理 springaop底层实现原理 spring aop原理解析 Spring的AOP底层解析,希望能帮助你了解 Spring的AOP底层解析。

  AOP原理的前置知识

   (1)动态代理(具体可查看 java的动态代理底层解析 )

   动态代理在Spring中的应用:
 

   1.AOP

   2.注解@Lazy

   (2)Spring中针对动态代理的封装

   1.ProxyFactory

   (1)介绍

   基于两种动态代理技术,在Spring中进行了封装,封装出来的类叫做ProxyFactory,表示是创建代理对象的一个工厂,使用起来会更加方便。

   (2)简单使用

   通过ProxyFactory,我们可以不再关系到底是用cglib还是jdk动态代理了,ProxyFactory会帮我们去判断,如果UserService实现了接口,那么ProxyFactory底层就会用jdk动态代理,如果没有实现接口,就会用cglib技术。

  

UserService userService1 = new UserService();

 

  ProxyFactory proxyFactory = new ProxyFactory();

  proxyFactory.setTarget(userService1);

  proxyFactory.addAdvice(new MethodInterceptor() {

   @Nullable

   @Override

   public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {

   System.out.println("切面逻辑 before...");

   Object result = invocation.proceed(); //执行被代理的方法,用于传递句柄

   //invocation.getMethod().invoke(invocation.getThis(), invocation.getArguments()); //执行被代理对象的方法

   System.out.println("切面逻辑 after...");

   return result;

  UserService userService2 = (UserService) proxyFactory.getProxy();

  userService2.test();

 

  

   (3)方法说明

   1、setTarget(),创建一个单例的代理对象

   2、addAdvice添加代理方法,该方法实现了Advice接口

   3、getProxy() 获取代理对象,AOP代理的Bean是通过该方法增强的

   (4)Advice的分类

   据我们想要对方法增强的话会有以下情况:

   1. Before Advice:方法之前执行(对应MethodBeforeAdvice接口)

  

public interface MethodBeforeAdvice extends BeforeAdvice {

 

   void before(Method method, Object[] args, @Nullable Object target) throws Throwable;

  }

 

   2. After returning advice:方法return后执行 (对应AfterReturningAdvice接口)

  

public interface AfterReturningAdvice extends AfterAdvice {

 

   void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;

  }

 

   3. After throwing advice:方法抛异常后执行(对应ThrowsAdvice接口)

  

/**

 

   * 注解上的示例

   * pre void afterThrowing([Method, args, target], ThrowableSubclass); /pre

   * p Some examples of valid methods would be:

   * pre public void afterThrowing(Exception ex) /pre

   * pre public void afterThrowing(RemoteException) /pre

   * pre public void afterThrowing(Method method, Object[] args, Object target, Exception ex) /pre

   * pre public void afterThrowing(Method method, Object[] args, Object target, ServletException ex) /pre

  public interface ThrowsAdvice extends AfterAdvice {}

  //为什么不定义方法,因为对于异常可以自定义,根据自己定义的不同异常进行捕捉执行拦截方法

 

  

   4. After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后(对应AfterAdvice接口)
 

   5. Around advice:这是功能最强大的Advice,可以自定义执行顺序(对应MethodInterceptor接口)

  

/**

 

   * 注解上有着对应的示例

   * pre "method "+i.getMethod()+" is called on "+

   * i.getThis()+" with args "+i.getArguments());

   * Object ret=i.proceed();

   * System.out.println("method "+i.getMethod()+" returns "+ret);

   * return ret;

   * /pre

  public interface MethodInterceptor extends Interceptor {

   Object invoke(MethodInvocation invocation) throws Throwable;

  }

 

  

   (5)链路形成的原理

   1.addAdvice添加代理方法展示(既然有多个,那么调用的时候必然也要都调用)

  

//这个方法本质上最终是将advisor参数添加到this.advisors属性里面

 

  public void addAdvisor(Advisor advisor) {

   int pos = this.advisors.size();

   addAdvisor(pos, advisor);

  }

 

  

   2.拦截器的句柄传递(分析invocation.proceed())

  

//ReflectiveMethodInvocation类#proceed()方法

 

  public Object proceed() throws Throwable {

   // currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1,当调用完了最后一个interceptor后就会执行被代理方法

   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {

   return invokeJoinpoint();

   // currentInterceptorIndex初始值为-1,根据下标获取拦截器

   Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

   // 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor

   // 如果没有匹配则递归调用proceed()方法,调用下一个interceptor

   if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

   InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;

   Class ? targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());

   // 动态匹配,根据方法参数匹配

   if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {

   return dm.interceptor.invoke(this);

   else {

   // 不匹配则执行下一个MethodInterceptor

   return proceed();

   else {

   // 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归,如:MethodBeforeAdviceInterceptor

   return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

  protected Object invokeJoinpoint() throws Throwable {

   return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);

  AopUtils类#invokeJoinpointUsingReflection方法

  public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args) throws Throwable {

   try {

   ReflectionUtils.makeAccessible(method);

   // 执行普通对象的方法,注意和@Configuration产生的代理对象的逻辑区别

   return method.invoke(target, args);

   catch (InvocationTargetException ex) {...} catch (IllegalArgumentException ex) {...} catch (IllegalAccessException ex) {...}

  }

 

  

   (6)Advisor的理解

   1.介绍说明
 

   跟Advice类似的还有一个Advisor的概念,一个Advisor是有一个Pointcut和一个Advice组成的,通过Pointcut可以指定要需要被代理的逻辑,比如一个UserService类中有两个方法,按上面的方法,这两个方法都会被代理,被增强,那么我们现在可以通过Advisor,来控制到具体代理哪一个方法。

   2.代码示例(产生的代理对象,只有在执行testAbc这个方法时才会被增强,会执行额外的逻辑,而在执行其他方法时是不会增强的)

  

public class UserServiceImpl implements UserService {

 

   @Override

   public String doSomething0(String param) {

   System.out.println("==============doSomething0");

   return "doSomething0";

   @Override

   public String doSomething1(String param) {

   System.out.println("==============doSomething1");

   return "doSomething1";

   @Override

   public String doSomething2(String param) {

   System.out.println("==============doSomething2");

   return "doSomething2";

   @Override

   public String myMethod(String param) {

   System.out.println("==============myMethod");

   return "myMethod";

  //操作代码

  UserService userService1 = new UserServiceImpl();

  ProxyFactory proxyFactory = new ProxyFactory();

  proxyFactory.setTarget(userService1);

  proxyFactory.addAdvisor(new PointcutAdvisor() {

   @Override

   public Pointcut getPointcut() {

   return new StaticMethodMatcherPointcut() {

   @Override

   public boolean matches(Method method, Class ? targetClass) {

   return method.getName().equals("doSomething1");

   @Override

   public Advice getAdvice() {

   return new MyAroundAdvice();

   @Override

   public boolean isPerInstance() {

   return false;

  UserService userService2 = (UserService) proxyFactory.getProxy();

  userService2.doSomething0("456");

 

  

   2.ProxyFactoryBean

   (1)介绍

   在使用Spring时,我们不会直接去使用ProxyFactory,因为我们希望所产生的代理对象能直接就是Bean能直接从Spring容器中得到代理对象,故使用ProxyFactoryBean。

   (2)简单使用

   通过这种方法来定义一个Bean,并且是经过了AOP的。但是这种方式只能针对某一个Bean。它是一个FactoryBean,所以利用的就是FactoryBean技术,间接的将类的代理对象作为了Bean。

   方法1:

  

@Bean

 

  public ProxyFactoryBean userService1() {

   UserService userService = new UserService();

   ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();

   proxyFactoryBean.setTarget(userService);

   proxyFactoryBean.addAdvisor(new PointcutAdvisor() {

   @Override

   public Pointcut getPointcut() {

   return new StaticMethodMatcherPointcut() {

   @Override

   public boolean matches(Method method, Class ? targetClass) {

   return method.getName().equals("doSomething1");

   @Override

   public Advice getAdvice() {

   return new MyAroundAdvice();

   @Override

   public boolean isPerInstance() {

   return false;

   return proxyFactoryBean;

  }

 

   方法2:

  

//把某个Advise或Advisor定义成为Bean,然后在ProxyFactoryBean中进行设置

 

  @Bean

  public MyAroundAdvice MyAroundAdvise() {

   return new MyAroundAdvice();

  
UserService userService = new UserService();

   ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();

   proxyFactoryBean.setProxyTargetClass(true);

   proxyFactoryBean.setTarget(userService);

   proxyFactoryBean.setInterceptorNames("myAroundAdvise");

   return proxyFactoryBean;

  }

 

  

   3.BeanNameAutoProxyCreator

   (1)介绍

   根据继承关系可知BeanNameAutoProxyCreator类继承了AbstractAdvisorAutoProxyCreator类(AbstractAutoProxyCreator有个抽象方法getAdvicesAndAdvisorsForBean方法)

   该类实现SmartInstantiationAwareBeanPostProcessor接口(该接口继承InstantiationAwareBeanPostProcessor接口【用于实例化的接口】)

   ProxyFactoryBean得自己指定被代理的对象,那么我们可以通过BeanNameAutoProxyCreator来通过指定某个bean的名字,来对该bean进行代理。

   通过BeanNameAutoProxyCreator可以对批量的Bean进行AOP,并且指定了代理逻辑,指定了一个InterceptorName,也就是一个Advise,前提条件是这个Advise也得是一个Bean,这样Spring才能找到的,但是BeanNameAutoProxyCreator的缺点很明显,它只能根据beanName来指定想要代理的Bean。

   (2)简单使用

  

@Bean

 

  public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {

   BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();

   beanNameAutoProxyCreator.setBeanNames("userSe*");

   beanNameAutoProxyCreator.setInterceptorNames("myAroundAdvise");

   beanNameAutoProxyCreator.setProxyTargetClass(true);

   return beanNameAutoProxyCreator;

  }

 

  

   4.DefaultAdvisorAutoProxyCreator

   (1)介绍

   根据继承关系可知DefaultAdvisorAutoProxyCreator类继承了AbstractAdvisorAutoProxyCreator类(AbstractAutoProxyCreator有个抽象方法getAdvicesAndAdvisorsForBean方法)

   该类实现SmartInstantiationAwareBeanPostProcessor接口(该接口继承InstantiationAwareBeanPostProcessor接口【用于实例化的接口】)

   (2)简单使用

  

@Bean

 

  public DefaultPointcutAdvisor defaultPointcutAdvisor() {

   NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();

   pointcut.addMethodName("test");

   DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();

   defaultPointcutAdvisor.setPointcut(pointcut);

   defaultPointcutAdvisor.setAdvice(new MyAroundAdvice());

   return defaultPointcutAdvisor;

  @Bean

  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {

   DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();

   defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);

   return defaultAdvisorAutoProxyCreator;

  }

 

  

   (3)思想说明

   1.通过DefaultAdvisorAutoProxyCreator会去找所有Advisor类型的Bean,根据Advisor中的PointCut和Advice信息,确定要代理的Bean以及代理逻辑。

   2.但通过这种方式,我们得依靠某一个类来实现定义我们的Advisor,或者Advise,或者Pointcut。

   3.要知道在bean的生命周期中存在BeanDefinition获取bean的元数据,为了更简化那就通过注解。

   4.通过在类中的方法上通过某些注解,来定义PointCut以及Advice,如

  

@Pointcut("execution(public * com.xxx.test.service.*.*(..))")

 

  public void pc1(){}

  
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

   System.out.println("==============AspectAnnotation around前置通知=========");

   Object result = joinPoint.proceed();

   System.out.println("==============AspectAnnotation around后置通知=========");

   return result;

  @Around(""execution(public void com.xxx.test.service.UserService.test())"")

  public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

   System.out.println("==============AspectAnnotation around前置通知=========");

   Object result = joinPoint.proceed();

   System.out.println("==============AspectAnnotation around后置通知=========");

   return result;

  }

 

   5.直接定义好了所要代理的方法(通过一个表达式),以及代理逻辑(被@Before修饰的方法),这样对于Spring来说,它要做的就是来解析这些注解了,解析之后得到对应的Pointcut对象、Advice对象,生成Advisor对象,扔进ProxyFactory中,进而产生对应的代理对象。

  

  

   5.TargetSource

   (1)介绍

   AOP中,被代理对象就是Bean对象,是由BeanFactory给我们创建出来的,但Spring AOP中提供了TargetSource机制,可以让我们用来自定义逻辑来创建被代理对象。

   (2)简单使用

  

ProxyFactory proxyFactory = new ProxyFactory();

 

  proxyFactory.setTargetSource(new TargetSource() {

   @Override

   public Class ? getTargetClass() {

   return UserService.class;

   @Override

   public boolean isStatic() {

   return true;

   @Override

   public Object getTarget() throws Exception {

   return new UserService();

   @Override

   public void releaseTarget(Object target) throws Exception {

  proxyFactory.addAdvice(new MyAroundAdvice());

  proxyFactory.setProxyTargetClass(true);

  proxyFactory.setFrozen(true); // frozen和static都为true,可以使得代理对象执行方法是保证被代理对象是同一个

  UserService proxy = (UserService) proxyFactory.getProxy();

  proxy.test();

 

  

   (3)简单说明

   1.首先proxyFactory要产生代理对象离不开被代理对象。那么我们要先知道setTarget与setTargetSource之间的关联:

  

public void setTarget(Object target) {

 

   setTargetSource(new SingletonTargetSource(target));

  @Override

  public void setTargetSource(@Nullable TargetSource targetSource) {

   this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);

  }

 

   2.通过源码可以看到即使是设置Target,其实都会被包装成TargetSource,那么对应的要获取Target,也就只能调用TargetSource类#getTarget()方法。(说明proxy代理的不是target,而是TargetSource)
 

   3.通常情况下,一个代理对象只能代理一个target,每次方法调用的目标也是唯一固定的target。但让proxy代理TargetSource,可以使得每次方法调用的target实例都不同(当然也可以相同,这取决于TargetSource实现)。这种机制使得方法调用变得灵活,可以扩展出很多高级功能,如:单利,原型,本地线程,目标对象池、运行时目标对象热替换目标源等等。(具体可查看 TargetSource目标源详解)

  

  对AOP的理解

  OOP表示面向对象编程,是一种编程思想,AOP表示面向切面编程,也是一种编程思想,而我们上面所描述的就是Spring为了让程序员更加方便的做到面向切面编程所提供的技术支持,也就说Spring提供了一套机制,可以让我们更加容易的来进行AOP,所以这套机制我们也可以称之为Spring AOP。

  但提供的注解的方式来定义Pointcut和Advice,Spring并不是首创,首创是AspectJ,而且也不仅仅只有Spring提供了一套机制来支持AOP,还有比如 JBoss 4.0、aspectwerkz等技术都提供了对于AOP的支持。而且注解的方式,Spring是依赖了AspectJ的,Spring是直接把AspectJ中所定义的那些注解直接拿过来用,自己没有再重复定义了,也仅仅只是把注解的定义赋值过来了,每个注解具体底层是怎么解析的,还是Spring自己做的,所以在用Spring时,如果你想用@Before、@Around等注解,是需要单独引入aspecj相关jar包的。

  注意:AspectJ是在编译时对字节码进行了修改,是直接在UserService类对应的字节码中进行增强的,也就是可以理解为是在编译时就会去解析@Before这些注解,然后得到代理逻辑,加入到被代理的类中的字节码中去的,所以如果想用AspectJ技术来生成代理对象 ,是需要用单独的AspectJ编译器的。我们在项目中很少这么用,仅仅只是用了@Before这些注解,而在启动Spring的过程中,Spring会去解析这些注解,然后利用动态代理机制生成代理对象的。

  
AOP中的核心概念

   1. Aspect:表示切面,比如被@Aspect注解的类就是切面,可以在切面中去定义Pointcut、Advice等等

   2. Join point:表示连接点,表示一个程序在执行过程中的一个点,比如一个方法的执行,比如一个异常的处理,在Spring AOP中,一个连接点通常表示一个方法的执行。

   3. Advice:表示通知,表示在一个特定连接点上所采取的动作。Advice分为不同的类型,在Spring中是用Interceptor拦截器来实现Advice,并且在连接点周围维护一个Interceptor链。

   4. Pointcut:表示切点,用来匹配一个或多个连接点,Advice与切点表达式是关联在一起的,Advice将会执行在和切点表达式所匹配的连接点上。

   5. Introduction:可以使用@DeclareParents来给所匹配的类添加一个接口,并指定一个默认实现。(这种不怎么用)

   示例

  

public interface CustomInterface {

 

   public void custom();

  public class DefaultCustomInterface implements CustomInterface{

   @Override

   public void custom() {

   System.out.println("custom..");

  @Aspect

  @Component

  public class MyAspect {

   //这种方式需要引入AspectJ

   @DeclareParents(value = "com.test.aop.introduction.CustomService", defaultImpl = DefaultCustomInterface.class)

   private CustomInterface customInterface;

  @ComponentScan

  @Configuration

  @EnableAspectJAutoProxy

  public class IntroductionDemo {

   public static void main(String[] args) {

   AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(IntroductionDemo.class);

   CustomService customService = applicationContext.getBean(CustomService.class);

   CustomInterface customInterface = (CustomInterface) customService;

   customInterface.custom();

  }

 

  

   6. Target object:目标对象,被代理对象

   7. AOP proxy:表示代理工厂,用来创建代理对象的,在Spring Framework中,要么是JDK动态代理,要么是CGLIB代理

   8. Weaving:表示织入,表示创建代理对象的动作,这个动作可以发生在编译时期(比如Aspejctj),或者运行时【如Spring AOP】。

  

  Advice在Spring AOP中对应API

   (1)Aspject中的注解,其中有五个是用来定义Advice的,表示代理逻辑,以及执行时机:
1. @Before
2. @AfterReturning
3. @AfterThrowing
4. @After
5. @Around
(2)Spring自己也提供了类似的执行实际的实现类:
1. 接口MethodBeforeAdvice,继承了接口BeforeAdvice
2. 接口AfterReturningAdvice
3. 接口ThrowsAdvice
4. 接口AfterAdvice
5. 接口MethodInterceptor
(3)Spring会把五个注解解析为对应的Advice类:
1. @Before:AspectJMethodBeforeAdvice,实际上就是一个MethodBeforeAdvice
2. @AfterReturning:AspectJAfterReturningAdvice,实际上就是一个AfterReturningAdvice
3. @AfterThrowing:AspectJAfterThrowingAdvice,实际上就是一个MethodInterceptor
4. @After:AspectJAfterAdvice,实际上就是一个MethodInterceptor
5. @Around:AspectJAroundAdvice,实际上就是一个MethodInterceptor

  

  ProxyFactory源码解析

   1.怎么判断是使用哪种动态代理?

  

//ProxyFactory类#getProxy()方法

 

  public Object getProxy() {

   //createAopProxy()在底层筛选方式

   //getProxy()方法返回代理对象

   return createAopProxy().getProxy();

  
//ProxyCreatorSupport类#createAopProxy()方法

  protected final synchronized AopProxy createAopProxy() {

   if (!this.active) {

   activate();

   //调用DefaultAopProxyFactory类(实现类AopProxyFactory接口)#createAopProxy(AdvisedSupport config)方法

   return getAopProxyFactory().createAopProxy(this);

  //DefaultAopProxyFactory类#createAopProxy方法

  public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

   // 是不是在GraalVM虚拟机上运行

   if (!NativeDetector.inNativeImage()

   // 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快

   // 或者isProxyTargetClass为true

   // 或者ProxyFactory有没有添加接口[setInterfaces()方法]

   (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.");

   //被代理的类是接口【setTargetClass】

   //判断是不是已经被代理的类

   if (targetClass.isInterface() Proxy.isProxyClass(targetClass)) {

   return new JdkDynamicAopProxy(config);

   return new ObjenesisCglibAopProxy(config);

   else {

   return new JdkDynamicAopProxy(config);

  }

 

  

   2.两种类型怎么产生动态代理的?

   (1)CGLib动态代理

  

public Object getProxy() {

 

   return getProxy(null);

  //删减日志与抛出异常部分

  //CglibAopProxy类#getProxy方法

  public Object getProxy(@Nullable ClassLoader classLoader) {

   try {

   // 被代理的类

   Class ? rootClass = this.advised.getTargetClass();

   Class ? proxySuperClass = rootClass;

   // 如果被代理类本身就已经是Cglib所生成的代理类了

   if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {

   // 获取真正的被代理类

   proxySuperClass = rootClass.getSuperclass();

   // 获取被代理类所实现的接口

   Class ? [] additionalInterfaces = rootClass.getInterfaces();

   for (Class ? additionalInterface : additionalInterfaces) {

   this.advised.addInterface(additionalInterface);

   // Validate the class, writing log messages as necessary.

   validateClassIfNecessary(proxySuperClass, classLoader);

   // Configure CGLIB Enhancer...

   Enhancer enhancer = createEnhancer();

   if (classLoader != null) {

   enhancer.setClassLoader(classLoader);

   if (classLoader instanceof SmartClassLoader

   ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {

   enhancer.setUseCache(false);

   // 被代理类,代理类的父类

   enhancer.setSuperclass(proxySuperClass);

   // 代理类额外要实现的接口

   enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));

   enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);

   enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

   // 获取和被代理类所匹配的Advisor

   Callback[] callbacks = getCallbacks(rootClass);

   Class ? [] types = new Class ? [callbacks.length];

   for (int x = 0; x types.length; x++) {

   types[x] = callbacks[x].getClass();

   // fixedInterceptorMap only populated at this point, after getCallbacks call above

   enhancer.setCallbackFilter(new ProxyCallbackFilter(

   this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));

   enhancer.setCallbackTypes(types);

   //返回产生的代理对象

   return createProxyClassAndInstance(enhancer, callbacks);

   catch (CodeGenerationException IllegalArgumentException ex) {..}

   catch (Throwable ex) {..}

  }

 

  

   (2)JDK动态代理

  

public Object getProxy() {

 

   return getProxy(ClassUtils.getDefaultClassLoader());

  //JdkDynamicAopProxy类#getProxy方法

  public Object getProxy(@Nullable ClassLoader classLoader) {

   // this实现了InvocationHandler

   return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);

  }

 

  

   3.两种类型的执行逻辑是怎么样的?

   (1)JDK动态代理

   1.JdkDynamicAopProxy类#invoke方法

  

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

 

   Object oldProxy = null;

   boolean setProxyContext = false;

   // 拿到ProxyFactory的配置对象【属性值private final AdvisedSupport advised;(AdvisedSupport是实现ProxyConfig配置接口的)】

   TargetSource targetSource = this.advised.targetSource;

   Object target = null;

   try {

   //判断如果被代理的目标对象要执行的方法是equal则执行JdkDynamicAopProxy(即代理对象的equal)方法,说明spring不对equal方法进行AOP拦截

   if (!this.equalsDefined AopUtils.isEqualsMethod(method)) {

   return equals(args[0]);

   //判断如果被代理的目标对象要执行的方法是hashcode则执行JdkDynamicAopProxy(即代理对象的hashcode)方法,同理spring也不对hashcode进行AOP拦截

   else if (!this.hashCodeDefined AopUtils.isHashCodeMethod(method)) {

   return hashCode();

   else if (method.getDeclaringClass() == DecoratingProxy.class) {

   // 得到代理对象的类型,而不是所实现的接口

   return AopProxyUtils.ultimateTargetClass(this.advised);

   //判断如果被代理的对象本身就是实现了Advised接口,也不做处理,直接执行,说明spring不做切面的切面

   else if (!this.advised.opaque method.getDeclaringClass().isInterface() method.getDeclaringClass().isAssignableFrom(Advised.class)) {

   return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);

   Object retVal;

   // 如果ProxyFactory的exposeProxy为true(可以对外暴露),则将代理对象设置到currentProxy这个ThreadLocal中去

   if (this.advised.exposeProxy) {

   //将代理对象设置到currentProxy这个ThreadLocal中去,作用是能通过ThreadLocal获取当前的代理对象(能在自己写的方法里面拿到代理对象)

   oldProxy = AopContext.setCurrentProxy(proxy);

   setProxyContext = true;

   // 被代理对象和代理类

   target = targetSource.getTarget();

   Class ? targetClass = (target != null ? target.getClass() : null);

   // 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor

   List Object chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

   if (chain.isEmpty()) {

   // 如果没有Advice,则直接调用对应方法

   Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

   retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);

   else {

   //包装成方法对象反射调用句柄

   MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

   //传递句柄

   retVal = invocation.proceed();

   // Massage return value if necessary.

   Class ? returnType = method.getReturnType();

   if (retVal != null retVal == target returnType != Object.class returnType.isInstance(proxy) !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {

   retVal = proxy;

   else if (retVal == null returnType != Void.TYPE returnType.isPrimitive()) {

   throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method);

   return retVal;

   finally {

   if (target != null !targetSource.isStatic()) {

   targetSource.releaseTarget(target);

   if (setProxyContext) {

   AopContext.setCurrentProxy(oldProxy);

  }

 

  

   2.AdvisedSupport类#getInterceptorsAndDynamicInterceptionAdvice方法

  

public List Object getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class ? targetClass) {

 

   // 代理对象在执行某个方法时,会根据当前ProxyFactory中所设置的Advisor根据当前Method再次进行过滤

   MethodCacheKey cacheKey = new MethodCacheKey(method);

   // 注意这个List,表示的就是Advice链

   // 被代理对象的某个方法已经被调用过,调用第一次就会获取一次,后面多次调用时,则需从缓存中直接获取,无需多次获取,这样就会提高性能

   List Object cached = this.methodCache.get(cacheKey);

   if (cached == null) {

   cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);

   this.methodCache.put(cacheKey, cached);

   return cached;

  }

 

  

   3.DefaultAdvisorChainFactory类#getInterceptorsAndDynamicInterceptionAdvice方法

  

//DefaultAdvisorChainFactory类#getInterceptorsAndDynamicInterceptionAdvice方法

 

  public List Object getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, @Nullable Class ? targetClass) {

   AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

   // 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor),添加的时候会控制顺序

   Advisor[] advisors = config.getAdvisors();

   List Object interceptorList = new ArrayList (advisors.length);

   Class ? actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());

   Boolean hasIntroductions = null;

   //遍历每个advisor

   for (Advisor advisor : advisors) {

   if (advisor instanceof PointcutAdvisor) {

   PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;

   // 先匹配类

   if (config.isPreFiltered() pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {

   // 再匹配方法

   MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();

   boolean match;

   if (mm instanceof IntroductionAwareMethodMatcher) {

   if (hasIntroductions == null) {

   hasIntroductions = hasMatchingIntroductions(advisors, actualClass);

   match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);

   else {

   match = mm.matches(method, actualClass);

   if (match) {

   // 如果匹配则将Advisor封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdvice

   MethodInterceptor[] interceptors = registry.getInterceptors(advisor);

   if (mm.isRuntime()) {

   for (MethodInterceptor interceptor : interceptors) {
// 运行时,封装成对应的 InterceptorAndDynamicMethodMatcher 拦截器对象。

   interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));

   else {

   interceptorList.addAll(Arrays.asList(interceptors));

   // 最终,interceptorList中存储的是当前正在执行的Method所匹配的MethodInterceptor,可能动态的,也可能是非动态的,

   // 找到Method所匹配的MethodInterceptor后,就会开始调用这些MethodInterceptor,如果是动态的,会额外进行方法参数的匹配

   //下面便是采用了修饰器模式的思。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: