欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Jdk动态代理与Cglib动态代理的简单使用

程序员文章站 2024-01-26 15:04:10
...

基本介绍        

        目前Java的动态代理主要分为jdk自带的动态代理java.lang.reflect.Proxy 和 谷歌的cglib

JDK动态代理介绍:

  1. 生成的代理对象不需要实现接口,但是目标对象要实现接口,否则无法使用动态代理,因为在转化过程中会抛错
  2. 代理对象的生成是利用JDK的api,动态的内存中构建代理对象
  3. 动态代理也叫:JDK代理、接口代理

JDK中生成的代理对象api

  1. 代理类包:java.lang.reflect.Proxy
  2. jdk实现代理只需要使用Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

应用一:动态代理实现方法侵入

        举例:有一个动物接口,接口中有两个方法,然后很多类都需要实现它并且复写这两个方法,但是我们想要在执行这个方法之前执行下自己自定义的一个方法,怎么做?那么这就可以利用动态代理去实现。

1.首先定义一个接口类,并且内部类dog去实现这个方法

package Aop.JDKProxy;

/**
 * @author Heian
 * @time 19/03/26 8:32
 */
public interface Animals {

    void run();

    String eat();

    static class Dog implements Animals{
        @Override
        public void run() {
            System.out.println ("狗开始跑");
        }

        @Override
        public String eat() {
            System.out.println ("狗开始吃");
            return "吃";
        }
    }

}

2.在定义一个测试类,当然因为要用到动态代理,所以要传入InvocationHandler这个类,并且复写这个类的invoke(Object proxy, Method method, Object[] args),此方法代理块里就可以填写的你的动态代理的逻辑了。

package Aop.JDKProxy;

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

/**
 * @author Heian
 * @time 19/03/26 8:35
 * 用途:
 */
public class MyProxy implements InvocationHandler {

    //返回的代理类
    private Object obj;

    /**
     * @proxy 被代理的对象
     * @method 要调用的方法
     * @agrs 方法调用所需参数
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //注入需要插入的方法
        command1();
        //执行被代理对象的方法、如果有返回值则赋值给ret
        Object ret = method.invoke (obj,args);//Objetc obj = obj.方法(agrs); 接口方法返回的对象,
        //注入需要插入的方法
        command2();
        return ret;
    }
    //绑定委托对象并返回一个代理类(代理类对象无需实现接口)
    public Object creatProxyInstance(Object object){
        this.obj = object;
        Object ob = Proxy.newProxyInstance (obj.getClass ().getClassLoader (),obj.getClass ().getInterfaces (),this);
        return ob;
    }

    //定义要插入的方法
    private void command1(){
        System.out.println ("主人发出命令");
    }
    private void command2(){
        System.out.println ("主人给出奖励");
    }

    public static void main(String[] args) {
        MyProxy myProxy = new MyProxy ();
        Animals dogAnimals =  (Animals) myProxy.creatProxyInstance (new Animals.Dog ());
        //Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to Aop.JDKProxy.Animals
        dogAnimals.run ();
        dogAnimals.eat ();
    }


}

        需要注意的就是在调用 myProxy.creatProxyInstance (目标类),目标类必须实现接口否则会抛出类转化异常,因为返回的是一个代理类对象 aaa@qq.com。

Jdk动态代理与Cglib动态代理的简单使用

备注:
Object ob = method.invoke(obj,args);比如我ob类有一个变量List,存在get方法
public List getList(){return list};
现在利用反射去调这个get方法,其中返回的就是是List类型,但是你传入的对象是一个ArrayList,此时就会抛出NoSuchMethodException,所以在利用发射去调用方法时,最好使用接口

应用二:动态代理实现事物(伪代码)

//接口
public interface IUserService {
    void saveUser();
}
//实现子类
public class UserServiceImpl implements IUserService {
    @Override
    public void saveUser() {
        System.out.println("保存用户信息");
    }
}
package Aop.JDKProxy2;

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

//代理类
public class DynamicProxy implements InvocationHandler {

    private Object targetObj;//相当于一个媒介

    public DynamicProxy(Object targetObj){
        this.targetObj = targetObj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj = null;
        try {
            startTranstraction();
            obj = method.invoke(targetObj, args);
        }catch (Exception e){
            rollback();
        }finally {
            conmmitTranstraction();
        }
        return obj;
    }

    public void startTranstraction(){
        System.out.println("开启事物");
    }
    public void conmmitTranstraction(){
        System.out.println("提交事物");
    }
    public void rollback(){
        System.out.println("回滚事物");
    }
    public static void main(String[] args) {
        UserServiceImpl target = new UserServiceImpl();
        DynamicProxy dynamicProxy = new DynamicProxy(target);
        IUserService proxy = (IUserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),dynamicProxy);
        proxy.saveUser();
    }
}
开启事物
保存用户信息
提交事物

 

相关标签: Java基础与高级