Spring AOP面向切面编程

目录

1.AOP概览

2.Spring AOP的使用举例

PointCut切入点

Advice通知

3.Spring AOP的实现原理

3.1运行时织入

3.1.1代理模式

3.1.2 JDK动态代理

3.1.3 cglib动态代理

3.1.4 Spring如何创建代理bean

4.Spring AOP的实现原理

4.1 链式调用

4.1.1 职责链模式

4.1.2 Spring内部实现

5. ProxyFactory实现AOP


1.AOP概览

AOP(Aspect Oriented Programming),什么是面向切面编程?

1)AOP是一种编程范式,不是编程语言

编程范式概览

  • 面向过程编程

  • 面向对象编程

  • 函数式编程

  • 事件驱动编程

  • 面向切面编程

2)AOP是为了解决特定问题,不是解决所有问题。AOP是OOP的补充,不是替代关系。

AOP的初衷是关注点隔离

切面隔离:将功能性需求和非功能性需求分离开来

做系统设计时,通常将大系统做分解,按业务功能分解成一个个低耦合、高内聚的模块。

分解后发现有趣的事情是,有些东西是公用的,或者跨越了多个模块。

  • 日志:对特定的操作输出日志来记录

  • 安全:在操作之前进行操作检查

  • 性能:统计每个方法的执行时间

  • 事务:方法开始前开始事务,方法结束后提交或回滚事务

我们可以将这些通用模块写好,在实现业务模块的时候去调用就好了。

但是,功能是实现了,但是业务代码中大部分都是日志、性能、事务等,几乎把真正的业务代码给淹没了!

最好的方法是将日志、安全、事务这样的代码和业务代码完全隔离开来,因为他们的关注点和业务代码的关注点完全不同。

他们之间的关系应该是正交的。如果把这个业务功能看成一层层面包的话, 这些日志/安全/事务 像不像一个个“切面”(Aspect) ?

如果我们能让这些“切面“能和业务独立,  并且能够非常灵活的“织入”到业务方法中, 那就实现了面向切面编程(AOP)!

AOP的应用场景

  • 审计日志:对特定的操作输出日志来记录

  • 权限控制:在操作之前进行操作检查

  • 性能监控:统计每个方法的执行时间

  • 事务控制:方法开始前开始事务,方法结束后提交或回滚事务

  • 缓存控制

  • 异常处理

根据织入时机的不同,AOP可以分为以下3种实现方式

1)编译期织入(AspectJ)

2)类加载时织入(AspectJ 5+)

3)运行时织入(Spring AOP)

2.Spring AOP的使用举例

Spring AOP实现权限控制:只有管理员可以进行修改操作

复制代码

@Service
public class ProductService {
    public Product get(Long id) {
        System.out.println("get product id = " + id);
        return new Product(id, "aaa");
    }
    @AdminOnly
    public void insert(Product product) {
        System.out.println("insert product");
    }
​
    @AdminOnly
    public void delete(Long id) {
        System.out.println("delete product id = " + id);
    }
}

复制代码

复制代码

@Aspect  //1)表明这个是一个切面类
@Component
public class SecurityAspect {
    //2)切入点
    @Pointcut("@annotation(AdminOnly)")
    public void adminOnly() {
    }
    //3)通知
    @Before("adminOnly()")
    public void check() {
        String user = CurrentUserHolder.get();
        if (!"admin".equals(user)) {
            throw new RuntimeException("operation not allow");
        }
    }
}

复制代码

PointCut切入点

PointCut(切入点):一个方法或一组方法(可以通过通配符支持)。

比如,“对于com.xxx这个包中所有类的execute方法” 。

Advice通知

Advice(通知):方法调用时需要做什么。比如,”在方法调用之前/之后 , 需要执行xxx操作“ 。

具体的通知类型包括:

  • before:前置通知,在方法调用前执行。

  • after returning:方法返回通知,在方法正常返回时执行。

  • throwing:方法异常通知,在方法抛出异常时执行。

  • after:方法结束通知,包含了方法正常返回和方法抛出异常两种情况。

  • around:环绕通知。

3.Spring AOP的实现原理

3.1运行时织入

根据织入时机的不同,AOP可以分为以下3种实现方式

1)编译期织入(AspectJ)

2)类加载时织入(AspectJ 5+)

3)运行时织入(Spring AOP)

Spring中的AOP实现是在运行时织入的。

运行时织入是如何实现的呢?通过动态代理的方式。

3.1.1代理模式

什么是代理模式

调用方Caller通过Proxy代理对象间接地与目标对象Target交互。

两个关键点:

1)Client客户端通过接口引用操作的对象Subject。且RealSubject真实对象和Proxy代理对象实现了同一个接口

2)Proxy代理对象会持有RealSubject真实对象的引用,真正要执行的方法委托给真实对象来执行,自己则执行一些额外的逻辑

public interface Subject {
    void request() throws Exception;
}
public class RealSubject implements Subject {
​
    public void request() {
        System.out.println("RealSubject execute request()");
    }
}

复制代码

public class Proxy implements Subject {
​
    private RealSubject realSubject;
​
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
    /**
    * 在真实对象request()方法之前或之后,可以执行一些额外的操作
    */
    public void request() throws Exception{
        System.out.println("before");
        try {
            realSubject.request();
        } catch (Exception e) {
            System.out.println("ex:" + e.getMessage());
            throw e;
        } finally {
            System.out.println("after");
        }
    }
}

复制代码

复制代码

public class Client {
​
    public static void main(String[] args) throws Exception{
        Subject subject = new Proxy(new RealSubject());
        subject.request();
    }
} 

复制代码

运行结果

before
RealSubject execute request()
after

上面代码展示的是静态代理的实现。

静态代理有如下缺点:

1)假设真实对象有100方法,则代理对象需要对100个方法进行委托。

2)且在这100个方法中代理对象执行的额外逻辑是一样的。

就像下面代码展示的那样。

public interface Subject {
    void request() throws Exception;
    void request2() throws Exception;
    void request3() throws Exception;
    void request4() throws Exception;

复制代码

public class RealSubject implements Subject {
​
    public void request() {
        System.out.println("RealSubject execute request()");
    }
​
    public void request2() {
        System.out.println("RealSubject execute request2()");
    }
​
    public void request3() {
        System.out.println("RealSubject execute request3()");
    }
​
    public void request4() {
        System.out.println("RealSubject execute request4()");
    }
}

复制代码

复制代码

public class Proxy implements Subject {
​
    private RealSubject realSubject;
​
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
​
    public void request() throws Exception{
        System.out.println("before");
        try {
            realSubject.request();
        } catch (Exception e) {
            System.out.println("ex:" + e.getMessage());
            throw e;
        } finally {
            System.out.println("after");
        }
    }
    //静态代理的缺点:
    //由于Subject添加了request2()、request3()、request4()方法,代理类中也要实现相应的方法
    //而且代理对象在request2()、request3()、request4()等方法中额外需要执行的逻辑都是一样的。
    public void request2() throws Exception{
        System.out.println("before");
        try {
            realSubject.request2();
        } catch (Exception e) {
            System.out.println("ex:" + e.getMessage());
            throw e;
        } finally {
            System.out.println("after");
        }
    }
​
    public void request3() throws Exception{
        System.out.println("before");
        try {
            realSubject.request3();
        } catch (Exception e) {
            System.out.println("ex:" + e.getMessage());
            throw e;
        } finally {
            System.out.println("after");
        }
    }
​
    public void request4() throws Exception{
        System.out.println("before");
        try {
            realSubject.request4();
        } catch (Exception e) {
            System.out.println("ex:" + e.getMessage());
            throw e;
        } finally {
            System.out.println("after");
        }
    }   
} 

复制代码

由于静态代理有上面的缺点,就产生了动态代理技术。

动态代理有两种实现方式

1)基于接口实现:JDK动态代理

2)基于继承实现:cglib动态代理

3.1.2 JDK动态代理

将上面的静态代理实现,改为使用JDK动态代理后,代码如下。

复制代码

public class JdkProxySubject implements InvocationHandler {
​
    private RealSubject realSubject;
​
    public JdkProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
​
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = null;
        try {
           result = method.invoke(realSubject, args);
        } catch (Exception e) {
            throw e;
        } finally {
            System.out.println("after");
        }
        return result;
    }
}

复制代码

复制代码

public class Client {
​
    public static void main(String[] args) throws Exception {
        //通过调用Proxy.newProxyInstance生成代理对象
        //方法参数为:1)classLoader  2)要代理的接口 3)代理对象的InvocationHandler
        //(通过方法参数也可以看出来,JDK代理只能通过代理接口来来实现动态代理)
        Subject subject = (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(),
                new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));
        //调用代理对象的request方法。
        //(根据InvocationHandler接口的定义,可以知道实际调用的是JdkProxySubject里的invoke方法)
        subject.request();
    }
}

复制代码

3.1.3 cglib动态代理

将上面的静态代理实现,改为使用cglib动态代理后,代码如下。

复制代码

public class DemoMethodInterceptor implements MethodInterceptor {
​
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("before in cglib");
        Object result = null;
        try {
            //注意:调用的是proxy.invokeSuper来调用目标类的方法
            result = methodProxy.invokeSuper(o, args);
        } catch (Exception e) {
            System.out.println("ex:" + e.getMessage());
            throw e;
        } finally {
            System.out.println("after in cglib");
        }
        return null;
    }
}

复制代码

复制代码

public class Client {
​
    public static void main(String[] args) throws Exception {
        //创建一个增强器
        Enhancer enhancer = new Enhancer();
        //设置目标类
        enhancer.setSuperclass(RealSubject.class);
        //设置拦截对象
        enhancer.setCallback(new DemoMethodInterceptor());
        //生成代理对象
        Subject subject = (Subject) enhancer.create();
        //调用代理对象的request方法
        subject.request();
    }
}

复制代码

3.1.4 Spring如何创建代理bean

动态代理有两种实现方式,JDK动态代理和cglib动态代理,那Spring是如何选择的?

ProxyFactoryBean的getObject()方法

复制代码

@Override
  public Object getObject() throws BeansException {
    initializeAdvisorChain();
    //对singleton和prototype的类型进行区分,生成对应的proxy
    if (isSingleton()) {
      return getSingletonInstance();
    }
    else {
      if (this.targetName == null) {
        logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
            "Enable prototype proxies by setting the 'targetName' property.");
      }
      return newPrototypeInstance();
    }
  }

复制代码

getSingletonInstance()方法

复制代码

  /**
   * Return the singleton instance of this class's proxy object,
   * lazily creating it if it hasn't been created already.
   * @return the shared singleton proxy
   */
  private synchronized Object getSingletonInstance() {
    if (this.singletonInstance == null) {
      this.targetSource = freshTargetSource();
      if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
        // Rely on AOP infrastructure to tell us what interfaces to proxy.
        Class<?> targetClass = getTargetClass();
        if (targetClass == null) {
          throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
        }
        setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
      }
      // Initialize the shared singleton instance.
      super.setFrozen(this.freezeProxy);
      this.singletonInstance = getProxy(createAopProxy());
    }
    return this.singletonInstance;
  }

复制代码

其中,生成代理实例的代码是这句。

this.singletonInstance = getProxy(createAopProxy());

可以将这句代码拆成下面两句。

1)aopProxy = createAopProxy()。

2)this.singletonInstance = getProxy(aopProxy) 。

createAopProxy()

createAopProxy()的方法如下。

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
      activate();
    }
    return getAopProxyFactory().createAopProxy(this);
  }

其中getAopProxyFactory()返回一个AopProxyFactory。在这里,返回的是AopProxyFactory的默认实现DefaultAopProxyFactory。

DefaultAopProxyFactory的createAopProxy()方法

复制代码

/**
 * Default {@link AopProxyFactory} implementation, creating either a CGLIB proxy
 * or a JDK dynamic proxy.
 *
 * <p>Creates a CGLIB proxy if one the following is true for a given
 * {@link AdvisedSupport} instance:
 * <ul>
 * <li>the {@code optimize} flag is set
 * <li>the {@code proxyTargetClass} flag is set
 * <li>no proxy interfaces have been specified
 * </ul>
 *
 * <p>In general, specify {@code proxyTargetClass} to enforce a CGLIB proxy,
 * or specify one or more interfaces to use a JDK dynamic proxy.
 */
@SuppressWarnings("serial")
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
​
  @Override
  public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    //如果满足下面3个条件,将使用cglib动态代理
    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.");
      }
      //以下两种情况除外
      //targetClass是接口   或者  targetClass本身就是使用jdk动态代理的proxy
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
        return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
    }
    //否则,使用jdk动态代理
    else {
      return new JdkDynamicAopProxy(config);
    }
  }
​
  /**
   * Determine whether the supplied {@link AdvisedSupport} has only the
   * {@link org.springframework.aop.SpringProxy} interface specified
   * (or no proxy interfaces specified at all).
   */
  private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
    Class<?>[] ifcs = config.getProxiedInterfaces();
    return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
  }
}
 

复制代码

1)如果目标对象实现了接口,则默认采用JDK动态代理

2)如果目标对象没有实现接口,则采用cglib进行动态代理

3)如果目标对象实现了接口,且强制cglib代理,则使用cglib动态代理

getProxy(aopProxy)

protected Object getProxy(AopProxy aopProxy) {
    return aopProxy.getProxy(this.proxyClassLoader);
}

如果入参中的aopProxy是JdkDynamicAopProxy的实例的话,会调用JdkDynamicAopProxy类中的方法。

如果入参中的aopProxy是ObjenesisCglibAopProxy的实例的话,会调用ObjenesisCglibAopProxy类中的方法。

JdkDynamicAopProxy.getProxy()方法

复制代码

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
  @Override
  public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
      logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  }
}

复制代码

可以看到JdkDynamicAopProxy实现了InvocationHandler接口,并通过Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)生成代理对象。

ObjenesisCglibAopProxy.getProxy()方法

与下面代码逻辑类似。

复制代码

        Enhancer enhancer = new Enhancer();
        //设置目标类
        enhancer.setSuperclass(RealSubject.class);
        //设置拦截对象
        enhancer.setCallback(new DemoMethodInterceptor());
        //生成代理对象
        Subject subject = (Subject) enhancer.create();
        //调用代理对象的request方法
        subject.request();

复制代码

4.Spring AOP的实现原理

4.1 链式调用

多个AOP 切面是如何叠加起作用的?

复制代码

public class Proxy implements Subject {
​
    private RealSubject realSubject;
​
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
    /**
    * realSubject.request()是目标方法
    * 在目标方法调用前、调用后、发生异常时,都需要被拦截
    * aop是如何实现将这些调用串起来的?
    */
    public void request() throws Exception{
        //before
        //记录调用次数
        //权限控制,仅管理员可以操作
        //开启事务
        System.out.println("before:记录调用次数"); 
        System.out.println("before:进行权限控制,仅管理员可以进行后续操作");
        System.out.println("before:开启事务");
        try {
            realSubject.request();
        } catch (Exception e) {
            //afterThrowing
            //事务失败,回滚操作
            System.out.println("afterThrowing:事务失败,回滚操作 ex:" + e.getMessage());
            throw e;
        } finally {
            //afterReturning
            //事务成功,提交操作
            System.out.println("afterReturning:事务成功,提交操作");
        }
    }
}

复制代码

4.1.1 职责链模式

4.1.1.1 V1

复制代码

public abstract class Handler {
​
    private Handler successor;
​
    public Handler getSuccessor() {
        return successor;
    }
​
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
​
    //对外暴露的方法
    public void execute() {
        handleProcess();
        if (successor != null) {
            successor.execute();
        }
    }
​
    // 需要子类实现
    protected abstract void handleProcess();
}

复制代码

复制代码

public class Client {
​
    static class HandlerA extends Handler {
​
        @Override
        protected void handleProcess() {
            System.out.println("handle by a");
        }
    }
​
    static class HandlerB extends Handler {
​
        @Override
        protected void handleProcess() {
            System.out.println("handle by b");
        }
    }
​
    static class HandlerC extends Handler {
​
        @Override
        protected void handleProcess() {
            System.out.println("handle by c");
        }
    }
    //缺点:各个handler之间的顺序需要显式指定
    //handlerA.setSuccessor(handlerB);
    //handlerB.setSuccessor(handlerC);
    public static void main(String[] args) {
        HandlerA handlerA = new HandlerA();
        HandlerB handlerB = new HandlerB();
        HandlerC handlerC = new HandlerC();
​
        handlerA.setSuccessor(handlerB);
        handlerB.setSuccessor(handlerC);
​
        handlerA.execute();
    }
}

复制代码

运行结果

handle by a
handle by b
handle by c

4.1.1.2 V2

复制代码

public abstract class ChainHandler {
​
    public void execute(Chain chain) {
        handleProcess();
        chain.proceed();
    }
​
    protected abstract void handleProcess();
}

复制代码

复制代码

public class Chain {
    //将各个handler保存在handlers这个list中
    //各个handler之间的执行顺序由chain来维持
    private List<ChainHandler> handlers;
    private int index = 0;
​
    public Chain(List<ChainHandler> handlers) {
        this.handlers = handlers;
    }
​
    public void proceed() {
        if (index >= handlers.size()) {
            return;
        }
        handlers.get(index++).execute(this);
    }
}

复制代码

复制代码

public class ChainClient {
    static class ChainHandlerA extends ChainHandler {
        @Override
        protected void handleProcess() {
            System.out.println("handle by a");
        }
    }
    static class ChainHandlerB extends ChainHandler {
        @Override
        protected void handleProcess() {
            System.out.println("handle by b");
        }
    }
    static class ChainHandlerC extends ChainHandler {
        @Override
        protected void handleProcess() {
            System.out.println("handle by c");
        }
    }
​
    public static void main(String[] args) {
        /**
        在list中的顺序决定了handler的执行顺序
        */
        List<ChainHandler> handlers = Arrays.asList(
                new ChainHandlerA(),
                new ChainHandlerB(),
                new ChainHandlerC()
        );
​
        Chain chain = new Chain(handlers);
        chain.proceed();
    }
}

复制代码

运行结果

handle by a
handle by b
handle by c

4.1.2 Spring内部实现

以JDK动态代理为例,调用目标对象的方法时,实际上调用的是代理对象的invoke方法。

JdkDynamicAopProxy的invoke方法

复制代码

 
 
/**
 * Implementation of {@code InvocationHandler.invoke}.
 * <p>Callers will see exactly the exception thrown by the target,
 * unless a hook method throws an exception.
 */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
​
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
​
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
​
Object retVal;
​
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
​
// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
​
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
​
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
​
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
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()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}

复制代码

JdkDynamicAopProxy的invoke方法核心代码如下:

复制代码

      //1).得到目标方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      //2). 调用拦截器链
      //如果chain是空的,直接调用target对象的method
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
      //如果chain不是空的,进行拦截器链的调用
else {
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}

复制代码

1)拦截器链是如何生成的

我们顺着this.advised.getInterceptorsAndDynamicInterceptionAdvice往下走。

复制代码

/**
 * Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
 * for the given method, based on this configuration.
 * @param method the proxied method
 * @param targetClass the target class
 * @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
 */
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
} 

复制代码

上面的this.advisorChainFactory其实是DefaultAdvisorChainFactory。

复制代码

public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
​
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
​
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    //遍历config.getAdvisors
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
          //调用registry.getInterceptors得到advisor的MethodInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
          //调用pointcutAdvisor.getPointcut().getMethodMatcher()得到pointcut的MethodMatcher
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
          //调用interceptorList.add将拦截器加入到拦截器链中
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
​
return interceptorList;
}
​
/**
 * Determine whether the Advisors contain matching introductions.
 */
private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
for (int i = 0; i < config.getAdvisors().length; i++) {
Advisor advisor = config.getAdvisors()[i];
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (ia.getClassFilter().matches(actualClass)) {
return true;
}
}
}
return false;
}
}

复制代码

List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass)

其实这里的config就是ProxyFactoryBean的实例。(config传入了个AdvisedSupport实例,ProxyFactoryBean继承了AdvisedSupport)

继续找ProxyFactoryBean的代码。

ProxyFactoryBean的getObject方法调用时,会对adviceChain进行初始化(如果未初始化的话)。

复制代码

 
@Override
public Object getObject() throws BeansException {
    //adviceChain拦截器链的初始化
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}

复制代码

initializeAdvisorChain的内部实现:

因为ProxyFactoryBean实现了BeanFactoryAware接口,因此可以拿到当前的容器实例beanFactory。

通过调用this.beanFactory.get(beanName)方法将各个advice bean拿出来,然后加入到list中。

initializeAdvisorChain的具体内部实现如下。

复制代码

/**
 * Create the advisor (interceptor) chain. Advisors that are sourced
 * from a BeanFactory will be refreshed each time a new prototype instance
 * is added. Interceptors added programmatically through the factory API
 * are unaffected by such changes.
 */
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
​
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
​
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
​
// Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
​
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
​
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
​
this.advisorChainInitialized = true;
}

复制代码

总结,在ProxyFactoryBean的getObject方法中,会初始化拦截器链,相关的bean是通过调用beanFactory.get(beanName)方法得到的。

2)拦截器链是如何链式调用的

ReflectiveMethodInvocation.proceed执行拦截器链的调用。

下面摘录了ReflectiveMethodInvocation的部分代码。

复制代码

 
//ReflectiveMethodInvocation实现了接口ProxyMethodInvocation,而ProxyMethodInvocation是MethodInvocation的子接口。
//因此,ReflectiveMethodInvocation实现了MethodInvocation接口。
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
​
protected final Object proxy;
​
protected final Object target;
​
protected final Method method;
​
protected Object[] arguments;
​
private final Class<?> targetClass;
​
/**
 * List of MethodInterceptor and InterceptorAndDynamicMethodMatcher
 * that need dynamic checks.
 */
  //拦截器列表
protected final List<?> interceptorsAndDynamicMethodMatchers;
​
/**
 * Index from 0 of the current interceptor we're invoking.
 * -1 until we invoke: then the current interceptor.
 */
private int currentInterceptorIndex = -1;
​
@Override
public Object proceed() throws Throwable {
//We start with an index of -1 and increment early.
    //如果拦截器list到了最后了,运行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//根据currentInterceptorIndex得到list中的拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    //1.如果拦截器中不仅有Interceptor,还需要进行动态方法匹配DynamicMethodMatcher
    //InterceptorAndDynamicMethodMatcher包含了Interceptor和DynamicMethodMatcher,
    //其中DynamicMethodMatcher用于运行时检查,用于在运行时判断方法是否需要拦截
    //(说明:MethodMatcher方法匹配分静态和动态两种
    //个人理解:
    //静态检查:比如你要拦截的方法名是精确的,就是某个类的某个方法,可以在程序非运行时,就可判断是否需要拦截
    //动态检查:比如你要拦截的某个方法,且要求入参为“aaa”,这种肯定需要运行时判断)
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
      //1.1 如果匹配上了,调用interceptor的invoke方法
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
        //如果匹配上了,调用拦截器方法
        //注意:interceptor.invoke(this)传入的是this。
        //而ReflectiveMethodInvocation实现了MethodInvocation接口
        //因此,传入的是一个MethodInvocation实例。
return dm.interceptor.invoke(this);
}
      //1.2 如果没有匹配上,
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
    //2. 如果拦截器就是个interceptor,调用invoker方法
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
}

复制代码

复制代码

public interface MethodInterceptor extends Interceptor {
​
/**
 * Implement this method to perform extra treatments before and
 * after the invocation. Polite implementations would certainly
 * like to invoke {@link Joinpoint#proceed()}.
 * @param invocation the method invocation joinpoint
 * @return the result of the call to {@link Joinpoint#proceed();
 * might be intercepted by the interceptor
 * @throws Throwable if the interceptors or the target object
 * throws an exception
 */
Object invoke(MethodInvocation invocation) throws Throwable;
} 

复制代码

MethodBeforeAdviceInterceptor:会在目标方法运行之前进行拦截。

复制代码

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
/**
 * Create a new MethodBeforeAdviceInterceptor for the given advice.
 * @param advice the MethodBeforeAdvice to wrap
 */
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
​
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
} 

复制代码

AfterReturningAdviceInterceptor:会在目标方法返回后进行拦截

复制代码

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
/**
 * Create a new AfterReturningAdviceInterceptor for the given advice.
 * @param advice the AfterReturningAdvice to wrap
 */
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
​
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}

复制代码

3)Spring使用职责链模式实现拦截器链链式调用

将上面调用拦截器链的简化下,如下。

public interface MethodInterceptor {
​
    Object invoke(MethodInvocation mi);
}

复制代码

public class MethodBeforeInterceptor implements MethodInterceptor {
​
    @Override
    public Object invoke(MethodInvocation mi) {
        before();
        return mi.proceed();
    }
​
    private void before() {
        System.out.println("Method before");
    }
}

复制代码

复制代码

public class AfterReturningInterceptor implements MethodInterceptor {
​
    @Override
    public Object invoke(MethodInvocation mi) {
        Object retVal = mi.proceed();
        afterReturning();
        return retVal;
    }
​
    private void afterReturning() {
        System.out.println("afterReturning");
    }
}

复制代码

public interface MethodInvocation {
​
    Object proceed();
}

复制代码

public class ReflectiveMethodInvocation implements MethodInvocation{
​
    private List<MethodInterceptor> interceptors;
​
    public ReflectiveMethodInvocation(List<MethodInterceptor> interceptors) {
        this.interceptors = interceptors;
    }
​
    private int currentInterceptorIndex = -1;
​
    public Object proceed() {
        if (currentInterceptorIndex == interceptors.size() - 1) {
            System.out.println("invoke target method");
            return "obj after invoke target method";
        }
        return interceptors.get(++currentInterceptorIndex).invoke(this);
    }
}

复制代码

复制代码

public class Client {
​
    public static void main(String[] args) {
        List<MethodInterceptor> interceptors = Arrays.asList(
                new AfterReturningInterceptor(),
                new MethodBeforeInterceptor()
        );
        ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(interceptors);
        invocation.proceed();
    }
}

复制代码

结果如下:

Method before
invoke target method
afterReturning

(这里抛个思考题:

运行结果与List<MethodInterceptor>中interceptor的顺序有关吗?

把new AfterReturningInterceptor()和new MethodBeforeInterceptor()换下顺序,结果会不同吗?

答案:无关,不会。

5. ProxyFactory实现AOP

通过配置的方式使用AOP时,是通过ProxyFactoryBean的getObject()方法得到代理对象的。

Spring 提供ProxyFactory类,可以通过编写代码的方式创建代理对象。

        TargetImpl target = new TargetImpl();
        ProxyFactory proxyFactory = new ProxyFactory(target);
        proxyFactory.addAdvisor(yourAdvisor);
        proxyFactory.addAdvice(yourAdvice);
        TargetImpl targetProxy = (TargetImpl)proxyFactory.getProxy();

ProxyFactory类提供的方法如下。

复制代码

/**
 * Factory for AOP proxies for programmatic use, rather than via a bean
 * factory. This class provides a simple way of obtaining and configuring
 * AOP proxies in code.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @since 14.03.2003
 */
@SuppressWarnings("serial")
public class ProxyFactory extends ProxyCreatorSupport {

    /**
     * Create a new ProxyFactory.
     */
    public ProxyFactory() {
    }
  
    public ProxyFactory(Object target) {
        setTarget(target);
        setInterfaces(ClassUtils.getAllInterfaces(target));
    }

    public ProxyFactory(Class<?>... proxyInterfaces) {
        setInterfaces(proxyInterfaces);
    }

    public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {
        addInterface(proxyInterface);
        addAdvice(interceptor);
    }

    public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) {
        addInterface(proxyInterface);
        setTargetSource(targetSource);
    }

    public Object getProxy() {
        return createAopProxy().getProxy();
    }

    public Object getProxy(ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) {
        return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();
    }

    @SuppressWarnings("unchecked")
    public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) {
        return (T) new ProxyFactory(proxyInterface, targetSource).getProxy();
    }

    public static Object getProxy(TargetSource targetSource) {
        if (targetSource.getTargetClass() == null) {
            throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");
        }
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTargetSource(targetSource);
        proxyFactory.setProxyTargetClass(true);
        return proxyFactory.getProxy();
    }
}

复制代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值