Spring AOP 的实现原理

Spring AOP 的实现原理



原理概述:织入的时机

1. 编译期(AspectJ)

2. 类加载时(AspectJ 5+)

3. 运行时(Spring AOP)

运行时织入原理

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

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


简单代理对象:

package com.example.proxy;

/**
 * com.example.proxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:[email protected]
 **/
public interface Subject {

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

/**
 * com.example.proxy
 * icourt
 * 2018/4/7
 * author:asange
 * email:[email protected]
 **/
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:[email protected]
 **/

/**
 * 代理对象
 */
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:[email protected]
 **/
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:[email protected]
 **/
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:[email protected]
 **/
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();
    }
}

通过上面 细心的应该发现,动态代理通过反射的方式,意味着不需要一个一个的委托方法实现,所以更适合代理原来对象更多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);
        }
    }


  /**
     * 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



缓存代理工厂 生成这些类



既然生成了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:[email protected]
 **/
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中方就可以看到了



这里贴出完整源码

//
// 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());
        }
    }
}



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:[email protected]
 **/
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:[email protected]
 **/
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();
    }
}


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如何叠加:责任链模式



简单责任链模式:

package com.example.proxy.chain;

/**
 * com.example.proxy.chain
 * icourt
 * 2018/4/8
 * author:asange
 * email:[email protected]
 **/
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:[email protected]
 **/
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();
    }

}


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

package com.example.proxy.chain2;

/**
 * com.example.proxy.chain
 * icourt
 * 2018/4/8
 * author:asange
 * email:[email protected]
 **/
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:[email protected]
 **/
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:[email protected]
 **/
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可以存放每个链,调用单链执行,同时执行的同时,又递归调用了责任链




猜你喜欢

转载自blog.csdn.net/axuanqq/article/details/79844314