动态代理之jdk代理

本文介绍了Java的JDK动态代理机制,如何在SpringBoot项目中使用它来增强IStudentService接口的实现,以及TransactionHandler类如何通过InvocationHandler接口实现方法拦截和事务管理。
摘要由CSDN通过智能技术生成

动态代理有jdk动态代理及cglib代理,下面描述jdk动态代理

jdk动态代理

看了 上云 老师的视频,整理下

pom文件

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
</dependencies>

目标类  IStudentServiceImpl

//目标执行接口
public interface IStudentService {

    void save();

    List<Student> query();
}


//目标执行类实现
@Service
public class IStudentServiceImpl implements IStudentService {

    private static final Logger logger= LoggerFactory.getLogger(IStudentServiceImpl.class);

    @Override
    public void save() {
        logger.info("新增功能...");
    }

    @Override
    public List<Student> query() {
        logger.info("查询功能...");
        return new ArrayList<>();
    }
}

增强类 TransactionService


@Service
public class TransactionService{

    private static final Logger logger= LoggerFactory.getLogger(TransactionService.class);

    public void before(){
        logger.info("开始事务...");
    }

    public void after(){
        logger.info("结束事务...");
    }

}

代理类


public class TransactionHandler implements InvocationHandler {

    private Object obj; //目标对象

    private TransactionService transactionService; //增强方法

    public TransactionHandler(Object obj, TransactionService transactionService) {
        this.obj = obj;
        this.transactionService = transactionService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        if ("save".equals(method.getName())) {
            transactionService.before();
            result = method.invoke(obj,args);
            transactionService.after();
        } else {
            result = method.invoke(obj,args);
        }
        return result;
    }
}

Junit测试类


public class TestStudent {

    @Test
    public void test(){
        //增强类
        TransactionService transactionService=new TransactionService();
        //目标类对象
        IStudentService studentService=new IStudentServiceImpl();
        //方法拦截处理器
        TransactionHandler transactionHandler = new TransactionHandler(studentService, transactionService);
        //获取代理实例对象
        IStudentService proxyInstance = (IStudentService)Proxy.newProxyInstance(IStudentServiceImpl.class.getClassLoader(), IStudentServiceImpl.class.getInterfaces(), transactionHandler);
        proxyInstance.save();
        saveProxyClass("D:\\programs\\idea\\projects\\demo1\\src\\");
    }

    private void saveProxyClass(String path){
        byte[] proxy1s = ProxyGenerator.generateProxyClass("$Proxy1", IStudentServiceImpl.class.getInterfaces());
        FileOutputStream out=null;
        try {
            out=new FileOutputStream(new File(path+"$Proxy1.class"));
            out.write(proxy1s);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(out!=null){
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

结论

可以看到:在src目录下生成一个class类[$Proxy1.class],此文件可以看到 该代理子类通过调用InvocationHandler的invoke方法实现了目标类的方法。

$Proxy1.class文件内容如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.example.demo.service.IStudentService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.List;

public final class $Proxy1 extends Proxy implements IStudentService {
    private static Method m1;
    private static Method m3;
    private static Method m4;
    private static Method m2;
    private static Method m0;

    public $Proxy1(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 void save() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final List query() throws  {
        try {
            return (List)super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    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 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"));
            m3 = Class.forName("com.example.demo.service.IStudentService").getMethod("save");
            m4 = Class.forName("com.example.demo.service.IStudentService").getMethod("query");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

由此可得出结论:底层实现了个Proxy的子类,Proxy里面有需要实现的增强方法,通过反射机制生成一个子类实现InvocationHandler接口,实现动态代理。
通过代理类对象调用方法时,会先调用其重写的invoke方法,里面再调用原方法。

  • 通过实现接口获取到接口的所有方法[$Proxy1.class文件实现目标IStudentService类]
  • 通过Proxy创建代理类实例[Proxy.newProxyInstance]
  • 通过反射机制,获取到一个个的方法对象[$Proxy1.class类]
  • 调用invocationHandler接口的invoke方法,从而实现业务的增强[TransactionHandler类文件实现InvocationHandler]
  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值