Spring日常笔记记录10--动态代理实现InvocationHandler

动态代理

动态代理是指,程序在整个运行构成中根本就不存在目标类的代理类,目标对象的代理对象只是由代理生成工具(不是真实定义的类)在程序运行时由JVM根据反射等机制动态生成的。代理对象与目标对象的代理关系在程序运行时才确立。

 

一、JDK动态代理

动态代理的实现方式常用的有两种:使用JDK的Proxy,与通过CGLIB生成代理。jdk的动态要求目标对象必须实现接口,这是Java设计上的要求

从jdk1.3以来,Java语言通过java.lang.reflect包提供三个支持代理模式Proxy,Method和InvocationHandler。

 

二、CGLIB动态代理

第三方的工具库,创建代理对象,原理是继承。通过继承目标类,创建子类。

子类就是代理对象,要求目标类不能是final的,方法也不能是final的

 

三、JDK动态代理底层实现

反射包 java.lang.reflect , 里面有三个类 : InvocationHandler , Method, Proxy.
1)InvocationHandler 接口(调用处理器):就一个方法invoke()
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke()方法中。

代理类完成的功能:
1. 调用目标方法,执行目标方法的功能
2. 功能增强,在目标方法调用时,增加功能。

 

2)方法原型:
参数: Object proxy:jdk创建的代理对象,无需赋值。
Method method:目标类中的方法,jdk提供method对象的
Object[] args:目标类中方法的参数, jdk提供的。

public Object invoke(Object proxy, Method method, Object[] args)

1) InvocationHandler 接口:表示你的代理要干什么
怎么用: 1.创建类实现接口InvocationHandler
2.重写invoke()方法, 把原来静态代理中代理类要完成的功能,写在这。


2)Method类:表示方法的, 确切的说就是目标类中的方法。
作用:通过Method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法的参数)
Object ret = method.invoke(service2, "李四");

说明: method.invoke()就是用来执行目标方法的,等同于静态代理中的
//向厂家发送订单,告诉厂家,我买了u盘,厂家发货
float price = factory.sell(amount); //厂家的价格。


3)Proxy类:核心的对象,创建代理对象。之前创建对象都是 new 类的构造方法()
现在我们是使用Proxy类的方法,代替new的使用。

方法: 静态方法 newProxyInstance()
作用是: 创建代理对象, 等同于静态代理中的TaoBao taoBao = new TaoBao();

 

三、JDK动态代理实现步骤:

1.创建目录类,SomeServiceImpl目标类,给它的doSome,doOther增加输出时间和事务。

 

 

 

 

 

 

2.创建InvocHandler接口的实现类,在这个类实现给目标方法增加功能。

package com.hlc.handler;

import com.hlc.util.ServiceTools;

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

public class MyInvocationHandler implements InvocationHandler {
    //目标对象
    private  Object target; //SomeServiceImpl类

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //通过代理对象执行时,会调用执行invoke()
        Object res = null;
        ServiceTools.doLog();
        //执行目标类的方法,通过Method类实现
        res = method.invoke(target,args);  //SomeServiceImpl , doOther() , doSome()
        ServiceTools.doTrans();
        //目标方法的执行结果
        return res;
    }
}

 

3.使用jdk中类Proxy,创建代理对象。实现创建对象的能力。

package com.hlc;

import com.hlc.handler.MyInvocationHandler;
import com.hlc.service.SomeService;
import com.hlc.service.impl.SomeServiceImpl;

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

public class MyApp {
    public static void main(String[] args) {
        //使用jdk的Proxy创建代理对象
        //创建目标对象
        SomeService target = new SomeServiceImpl();

        //使用InvocationHandler对象
        InvocationHandler handler = new MyInvocationHandler(target);

        //使用Proxy创建代理
        SomeService proxy = (SomeService) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),handler
        );

        //通过代理执行方法,会调用handler中的invoke()
        proxy.doSome();
    }
}

运行结果:

执行了MyInvocationHandler中的involved
非业务方法,方法的执行时间:Mon Jul 26 00:25:49 CST 2021
执行业务方法doSome
方法执行完毕后,提交事务

 

 

四、动态代理的作用

1.在目标类源代码不改变的情况下,增加功能

2.减少代码的重复

3.专注业务逻辑代码

4.解耦合,让业务功能和日志、事务和非事务功能分离

posted @ 2021-07-26 00:30  Brack_Pearl  阅读(481)  评论(0)    收藏  举报