欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring AOP 的实现原理

程序员文章站 2022-07-12 14:32:29
...

Spring AOP 的实现原理

Spring AOP 的实现原理

 

原理概述:织入的时机

1. 编译期(AspectJ)

2. 类加载时(AspectJ 5+)

3. 运行时(Spring AOP)

运行时织入原理

1. 从静态代理到动态代理

2. 基于接口代理与基于继承代理

Spring AOP 的实现原理

简单代理对象:
 

package com.example.proxy;

/**
 * com.example.proxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/
public interface Subject {

    void request();
}
package com.example.proxy;

/**
 * com.example.proxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("========>realSubject request");
    }
}

 

package com.example.proxy;

/**
 * com.example.proxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/

/**
 * 代理对象
 */
public class Proxy implements Subject {

    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("======>before");
        /**
         * 委托目标对象执行
         */
        try {
            this.realSubject.request();
        } catch (Exception e) {
            System.out.println("======>exception:" + e);
            //代理对象并不会改变这个对象的方法
            throw e;
        } finally {
            System.out.println("======>after");
        }

    }
}
package com.example.proxy;

/**
 * com.example.proxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/
public class Client {

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

jdk代理演示

静态代理和动态代理

1. 静态代理缺点 不灵活,方法数太多,尾大不掉

2. 动态代理的两类实现: 基于接口代理与基于继承代理

3. 两类代理的代表:JDK代理与Cglib代理

JDK代理实现:

1.类:java.lang.reflect.Proxy

2.接口InvocationHandler

3.只能基于接口进行动态代理

package com.example.proxy.jdkproxy;

import com.example.proxy.RealSubject;

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

/**
 * com.example.proxy.jdkproxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/
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 {
        try {
            System.out.println("==========>before");
            //用反射动态执行
            return method.invoke(realSubject, args);
        } catch (Exception e) {
            throw e;
        } finally {
            System.out.println("==========>after");
        }
    }
}

通过反射动态执行

package com.example.proxy.jdkproxy;

import com.example.proxy.RealSubject;
import com.example.proxy.Subject;

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

/**
 * com.example.proxy.jdkproxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/
public class JdkProxyClient {

    public static void main(String[] args) {
        Subject subject= (Subject) Proxy.newProxyInstance(
                JdkProxyClient.class.getClassLoader(),
                new Class[]{Subject.class},
                new JdkProxySubject(new RealSubject()));
        subject.request();
    }
}

Spring AOP 的实现原理

 

通过上面 细心的应该发现,动态代理通过反射的方式,意味着不需要一个一个的委托方法实现,所以更适合代理原来对象更多action的场景

 

jdk代理源码实现

1. Proxy.newProxyInstance

2.getProxyClass0 ProxyClassFactory,ProxyGenerator

3.newInstance

源码:

 @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

Spring AOP 的实现原理

 

  /**
     * Generate a proxy class.  Must call the checkProxyAccess method
     * to perform permission checks before calling this.
     */
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

 

这里是从缓存中拿去class

Spring AOP 的实现原理

 

缓存代理工厂 生成这些类

Spring AOP 的实现原理

 

既然生成了class字节码文件,那我们怎么查看呢?
 

  //生成$Proxy0的class文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
package com.example.proxy.jdkproxy;

import com.example.proxy.RealSubject;
import com.example.proxy.Subject;

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

/**
 * com.example.proxy.jdkproxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/
public class JdkProxyClient {

    public static void main(String[] args) {
        //生成$Proxy0的class文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        Subject subject= (Subject) Proxy.newProxyInstance(
                JdkProxyClient.class.getClassLoader(),
                new Class[]{Subject.class},
                new JdkProxySubject(new RealSubject()));
        subject.request();
    }
}

我们运行一下

在idea中方就可以看到了

Spring AOP 的实现原理

 

这里贴出完整源码
 

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.example.proxy.Subject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Subject {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void request() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.example.proxy.Subject").getMethod("request");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

Spring AOP 的实现原理

 

 

cglib方式代理:

package com.example.proxy.cglibproxy;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * com.example.proxy.cglibproxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/
public class CglibInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        try {
            System.out.println("========cglib before");
            return methodProxy.invokeSuper(o,args);
        } catch (Throwable e) {
            System.out.println("========cglib exc:"+e);
            throw e;
        }
        finally {
            System.out.println("========cglib after");
        }
    }
}
package com.example.proxy.cglibproxy;

import com.example.proxy.RealSubject;
import com.example.proxy.Subject;
import org.springframework.cglib.proxy.Enhancer;

/**
 * com.example.proxy.cglibproxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:aaa@qq.com
 **/
public class CglibClient {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new CglibInterceptor());
        Subject subject = (Subject) enhancer.create();
        subject.request();
    }
}


Spring AOP 的实现原理

 

jdk与cglib代理对比

 

1.Jdk只能针对有接口的类的的接口方法进行动态代理

2.cglib基于继承来实现代理,无法对static,final类进行代理

3.cglib基于继承来实现代理,无法对private static方法进行代理

 

Spring AOP代理

在springframwork中有一个defaultAopProxyFactory

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.aop.framework;

import java.io.Serializable;
import java.lang.reflect.Proxy;
import org.springframework.aop.SpringProxy;

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    public DefaultAopProxyFactory() {
    }

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

    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代理

强制spring使用cglib代理:

package com.example.proxy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
//强制使用cglib代理
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopProxyApplication {

	public static void main(String[] args) {
		SpringApplication.run(AopProxyApplication.class, args);
	}
}

多个aop如何叠加:责任链模式

Spring AOP 的实现原理

 

简单责任链模式:

package com.example.proxy.chain;

/**
 * com.example.proxy.chain
 * icourt
 * 2018/4/8
 * author:asange
 * email:aaa@qq.com
 **/
public abstract class Handler {

    private Handler sucessor;

    public Handler getSucessor() {
        return sucessor;
    }

    public void setSucessor(Handler sucessor) {
        this.sucessor = sucessor;
    }


    public void execute() {
        handleProcess();
        if (sucessor != null) {
            sucessor.execute();
        }
    }

    protected abstract void handleProcess();
}
package com.example.proxy.chain;

/**
 * com.example.proxy.chain
 * icourt
 * 2018/4/8
 * author:asange
 * email:aaa@qq.com
 **/
public class ChainClient {
    static class HanlderA extends Handler {

        @Override
        protected void handleProcess() {
            System.out.println("=========>handle by a");
        }
    }

    static class HanlderB extends Handler {

        @Override
        protected void handleProcess() {
            System.out.println("=========>handle by b");
        }
    }

    static class HanlderC extends Handler {

        @Override
        protected void handleProcess() {
            System.out.println("=========>handle by c");
        }
    }

    public static void main(String[] args) {
        Handler handlerA = new HanlderA();
        Handler handlerB = new HanlderB();
        Handler handlerC = new HanlderC();

        //建立关系
        handlerA.setSucessor(handlerB);
        handlerB.setSucessor(handlerC);

        handlerA.execute();
    }

}

Spring AOP 的实现原理

 

可以看到是用手动指定下一个链,不灵活,下面用一个递归灵魂创建责任链

package com.example.proxy.chain2;

/**
 * com.example.proxy.chain
 * icourt
 * 2018/4/8
 * author:asange
 * email:aaa@qq.com
 **/
public abstract class ChainHandler {

    public void execute(Chain chain) {
        handleProcess();
        if (chain != null) {
            chain.execute();
        }
    }

    protected abstract void handleProcess();
}
package com.example.proxy.chain2;

import java.util.ArrayList;
import java.util.List;

/**
 * com.example.proxy.chain
 * icourt
 * 2018/4/8
 * author:asange
 * email:aaa@qq.com
 **/
public class Chain {

    private List<ChainHandler> chainHandlerList = new ArrayList();

    public Chain(List<ChainHandler> chainHandlerList) {
        this.chainHandlerList = chainHandlerList;
    }

    int index;

    public void execute() {
        if (index >= chainHandlerList.size()) {
            return;
        }
        chainHandlerList.get(index++)
                .execute(this);
    }
}
package com.example.proxy.chain2;

import java.util.Arrays;

/**
 * com.example.proxy.chain2
 * icourt
 * 2018/4/8
 * author:asange
 * email:aaa@qq.com
 **/
public class ChainClient {

    static class ChainHandlerA extends ChainHandler {

        @Override
        protected void handleProcess() {
            System.out.println("===================>handleProcess a");
        }
    }

    static class ChainHandlerB extends ChainHandler {

        @Override
        protected void handleProcess() {
            System.out.println("===================>handleProcess b");
        }
    }

    static class ChainHandlerC extends ChainHandler {

        @Override
        protected void handleProcess() {
            System.out.println("===================>handleProcess c");
        }
    }

    public static void main(String[] args) {
        ChainHandler chainHandlerA = new ChainHandlerA();
        ChainHandler chainHandlerB = new ChainHandlerB();
        ChainHandler chainHandlerC = new ChainHandlerC();

        Chain chain = new Chain(Arrays.asList(chainHandlerA, chainHandlerB, chainHandlerC));
        chain.execute();

    }
}

在这里 chain里面创建了一个list可以存放每个链,调用单链执行,同时执行的同时,又递归调用了责任链

Spring AOP 的实现原理