AOP的底层实现---动态代理

动态代理分为两种:JDK动态代理与CGLIB动态代理.

什么是代理(proxy)?什么是动态代理?

代理: 代理拥有被代理的属性与方法,可以代表被代理类完成被代理类不想做,不得不做,或者想做却不能做的任务。比如说,一个方法无法通过自身来调用,可以通过代理来调用。

动态代理:代理者是全能的,能够代理任何的对象,所以在代理前都不清楚要代理什么内容,只有在创建号代理之后才能明确。

一、通过JDK实现切面逻辑的动态代理

接口代码

package JDKproxy;
public interface Userinterface {
void addUser();
}

接口实现类:

package JDKproxy;
public class UserinterfaceImpl implements Userinterface { 
 public void addUser() {  
         System.out.println("添加用户");   
          }
          }
          

前置切入的方法与后置切入的方法

public static void check(){
    System.out.println("检查用户属性");
}
public static void save(){
    System.out.println("用户属性归档");
}

动态代理的实现类


package JDKproxy;

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

//JDK提供的调用方法的一个接口,代理机制下调用方法的接口,必须实现invoke()方法
public class JDKProxy implements InvocationHandler {

//被代理的对象
    public Object targetobj;
    //创建被代理对象
    public Object createProxy(Object targetobj ){
        this.targetobj=targetobj;
        //创建一个代理对象的方法,第一个参数获得类加载器,帮助动态或者静态加载类,每一个类都有一个类加载器,第二个参数获得对象所在的类所实现的任何一个接口。
        //第三个参数是是invocationhandle接口本身
        return Proxy.newProxyInstance(targetobj.getClass().getClassLoader(),targetobj.getClass().getInterfaces(),this);
    }
    //传入一个被代理对象,返回一个代理的对象
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //真正调用方法的地方
        //切入前,前置切入
        Aspect.check();
        Object ret=  method.invoke(targetobj,args);
        //切入后,后置切入
        Aspect.save();
        return ret;

    }
}

主方法:

package JDKproxy;

public class RunTest {
    public static void main(String[] args) {
        Userinterface userinterface=new UserinterfaceImpl();
//        userinterface.addUser();
        //创建userinterface的动态代理
        Userinterface proxy=(Userinterface) new JDKProxy().createProxy(userinterface);
        //通过动态代理调用被代理对象的方法
        proxy.addUser();
    }
}

首先,通过createProxy()的newInstance方法创建被代理对象的动态代理对象,在创建好代理对象之后,代理对象调用方法时,会自动调用invoke()方法,在invoke方法里实现拓展方法。并通过method反射机制实现之前的方法。

二、CGLIB实现动态代理

CGLIb是通过字节码技术,在运行时动态创建被代理者的子类。

第一步 添加cglib依赖

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.10</version>
</dependency>

第二步 创建CGLIB代理实现类

package CGLIBProxy;

import JDKproxy.Aspect;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CGlibproxy implements MethodInterceptor {
    //在字节码阶段,调用代码的时候会调用的方法
    public Object createProxy(Object targetobj){
        //通过Enhance类来创建CGlib的动态代理对象
        Enhancer enhancer=new Enhancer();
        //设置它的类为被代理对象所在的类
        enhancer.setSuperclass(targetobj.getClass());
        //回调
        enhancer.setCallback(this);
        //创建代理对象
        return enhancer.create();
    }
    public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {


        Aspect.check();
        //切面逻辑在这里触发,调用父类的方法
        methodProxy.invokeSuper(proxy,objects);
        Aspect.save();
        return null;
    }
}

实现MethodInterceptor接口,使用createproxy方法创建产生代理对象,在代理对象调用被代理对象的方法时会自动调用intercept方法,此方法也就是切面逻辑出发的地方。

package CGLIBProxy;

public class Runtest {
    public static void main(String[] args) {
        User user=new User();
        user.addUser();
        //createProxy的参数时被代理的对象,此方法用于产生代理
        User Proxy=(User) new CGlibproxy().createProxy(user);
        Proxy.addUser();
    }
}

三、二者区别

1、JDK动态代理是在代码创建阶段生成的,优点:创建对象很快,但整体运行逻辑会很慢。
2、CGLIB在代理运行阶段创捷一个子类继承被代理类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值