Spring AOP的底层实现是怎样的?
文章目录
- Spring AOP底层实现
- 静态代理
- 动态代理
- 1、JDK动态代理(必须有接口)
- 实例:
- 2、CGLIB动态代理(不需要类继承任何接口,字节码技术)
- 实例:
Spring AOP底层实现
代理设计模式:将委托类融入到代理类中。
静态代理
一个接口,两个实现类,代理实现类组合真实实现类
一种根据上面的理论,很自然会想到的一种不依赖于其他技术的代理模式实现方式。而他的实现过程如下图。
动态代理
动态代理的动态, 就是可以动态的切换真实实现类, 也就是说可以一个代理类(相同的代码, 相同的增强操作)应对一堆不确定的真实实现类.
1、JDK动态代理(必须有接口)
通过实现InvocationHandlet接口,并重写里面的invoke方法,通过为proxy类指定classLoader和一组interfaces来创建动态代理。
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了
动态代理就是为了解决静态代理不灵活的缺陷而产生的。静态代理是固定的,一旦确定了代码,如果委托类新增一个方法,而这个方法又需要增强,那么就必须在代理类里重写一个带增强的方法。而动态代理可以灵活替换代理方法,动态就是体现在这里。
JDK动态代理具体实现原理:
1、通过实现InvocationHandlet接口创建自己的调用处理器
2、通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理
3、通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型
4、通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入
实例:
public interface TargetClass {
void sayHello();
}
public class TargetClassImpl implements TargetClass{
public void sayHello() {
System.out.println("你好");
}
}
public class JdkProxy implements InvocationHandler {
private TargetClass targetClass;
public Object createProxy(TargetClass targetClass){
//传入真实实现类, 本身要做的事情会由他自己做, 代理类会额外进行其他增强操作
this.targetClass = targetClass;
//获取本类类加载器
ClassLoader classLoader = JdkProxy.class.getClassLoader();
///获取被代理对象的所有接口
Class[] clazz = targetClass.getClass().getInterfaces();
System.out.println(clazz.length);
//生成代理类并返回
return Proxy.newProxyInstance(classLoader, clazz, this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDKProxy前置增强");
Object obj = method.invoke(targetClass,args);
System.out.println("JDKProxy后置增强");
return obj;
}
}
public class Test {
public static void main(String[] args) {
JdkProxy jdkProxy = new JdkProxy();
TargetClass targetClass = new TargetClassImpl();
TargetClass targetClass1 = (TargetClass) jdkProxy.createProxy(targetClass);
targetClass1.sayHello();
}
2、CGLIB动态代理(不需要类继承任何接口,字节码技术)
CGlib包在Spring core包里。
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
实例:
public class CGlibTaretClass {
public void sayHello(){
System.out.println("我是CGlib,我不需要接口");
}
}
package CGlibProxyTest;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGlibProxy implements MethodInterceptor{
//代理方法
public Object createProxy(Object target){
//创建一个动态类对象
Enhancer enhancer = new Enhancer();
//确定要增强的类,设置期父类
enhancer.setSuperclass(target.getClass());
//添加回调函数
enhancer.setCallback(this);
//返回创建的代理类
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("CGlib前置增强");
Object obj = methodProxy.invokeSuper(o,objects);
System.out.println("CGlib后置增强");
return obj;
}
}
public class Test {
public static void main(String[] args) {
CGlibProxy cGlibProxy = new CGlibProxy();
CGlibTaretClass cGlibTaretClass = new CGlibTaretClass();
CGlibTaretClass cGlibTaretClass1 = (CGlibTaretClass)cGlibProxy.createProxy(cGlibTaretClass);
cGlibTaretClass1.sayHello();
}
还没有评论,来说两句吧...