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: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();
}
}
通过上面 细心的应该发现,动态代理通过反射的方式,意味着不需要一个一个的委托方法实现,所以更适合代理原来对象更多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: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中方就可以看到了
这里贴出完整源码
//
// 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: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();
}
}
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: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();
}
}
可以看到是用手动指定下一个链,不灵活,下面用一个递归灵魂创建责任链
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可以存放每个链,调用单链执行,同时执行的同时,又递归调用了责任链