Spring AOP 的实现原理

xiaoxiao2021-02-28  20

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:xuanyouwu@163.com **/ public interface Subject { void request(); } package com.example.proxy; /** * com.example.proxy * icourt * 2018/4/7 * author:asange * email:xuanyouwu@163.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:xuanyouwu@163.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:xuanyouwu@163.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:xuanyouwu@163.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:xuanyouwu@163.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(); } }

 

通过上面 细心的应该发现,动态代理通过反射的方式,意味着不需要一个一个的委托方法实现,所以更适合代理原来对象更多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:xuanyouwu@163.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中方就可以看到了

 

这里贴出完整源码  

// // 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:xuanyouwu@163.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:xuanyouwu@163.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(); } }

 

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:xuanyouwu@163.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:xuanyouwu@163.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(); } }

 

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

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

 

 

 

转载请注明原文地址: https://www.6miu.com/read-2499978.html

最新回复(0)