Java动态代理

一个动态代理的小demo

对保存数据这一行为模拟添加事务管理

动态代理的特点
进行代理的对象不需要实现接口,但是要求被代理的目标对象必须实现接口,否则不能使用动态代理。先给出一个接口:IUserDao

接口:IUserDao

package com.DynamicProxy;

public interface ISaveInfoDao {
    public void save();
}

需要进行代理的目标对象

package com.DynamicProxy;

//目标对象
public class SaveInfoDao implements ISaveInfoDao {
    @Override
    public void save() {
        System.out.println("保存数据");
    }
}

java动态代理机制中有两个重要的类和接口InvocationHandler(接口)和Proxy(类),这一个类Proxy和接口InvocationHandler是实现动态代理的核心。

每一个动态代理类的调用处理程序都必须实现InvocationHandler接口,并且每个代理类的实例都关联到了实现该接口的动态代理类调用处理程序中,当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用

定义一个代理类的调用处理程序,每个代理类的调用处理程序都必须实现InvocationHandler接口,实现如下:

package com.DynamicProxy;

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

public class SelDefHandler implements InvocationHandler {

    //需要代理的目标对象
    private Object target;

    //构造函数,给目标对象赋值
    public SelDefHandler(Object obj) {
        this.target = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //代理对象相较于目标对象多出的行为(根据业务需求自定义)
        System.out.println("开启事务");
        //执行目标对象方法
        Object returnValue = method.invoke(target, args);
        //代理对象相较于目标对象多出的行为(根据业务需求自定义)
        System.out.println("提交事务");
        return returnValue;
    }
}

或者通过代理对象工厂产生代理对象

package com.DynamicProxy;

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

//动态代理对象
public class ProxyFactory {
    //代理类中的真实对象(即需要代理的目标对象,发生行为的真实对象)
    private Object target;

    //构造函数,给我们的目标对象赋值
    public ProxyFactory(Object target) {
        this.target = target;
    }

/*
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
static Object newProxyInstance(ClassLoader loader,  	//指定当前目标对象使用类加载器
                                  Class<?>[] interfaces,//目标对象实现的接口的类型
                                  InvocationHandler h //事件处理器
)
在代理实例上处理方法调用并返回结果。
Object invoke(Object proxy, Method method, Object[] args)
*/

    // 为目标对象生成代理对象
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                        target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //代理对象相较于目标对象多出的行为(根据业务需求自定义)
                        System.out.println("开启事务");
                        // 执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        //代理对象相较于目标对象多出的行为(根据业务需求自定义)
                        System.out.println("提交事务");
                        return returnValue;
                    }
                });
    }
}

测试

package com.DynamicProxy;

import org.junit.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class TestProxy {

    @Test
    //直接生成代理对象
    public void testDynamicProxyDirect() {
        //需要代理的目标对象,核心行为真实执行者
        ISaveInfoDao target1 = new SaveInfoDao();
        //代理对象的调用处理程序,我们将要代理的真实对象传入代理对象的调用处理的构造函数中,最终代理对象的调用处理程序会调用真实对象的方法
        InvocationHandler handler = new SelDefHandler(target1);
        /**
         通过Proxy类的newProxyInstance方法创建代理对象,方法中的参数如下:
         第一个参数:people.getClass().getClassLoader(),使用handler对象的classloader对象来加载我们的代理对象
         第二个参数:people.getClass().getInterfaces(),这里为代理类提供的接口是真实对象实现的接口,这样代理对象就能像真实对象一样调用接口中的所有方法
         第三个参数:handler,我们将代理对象关联到上面的InvocationHandler对象上
         */
        ISaveInfoDao proxy1 = (ISaveInfoDao)Proxy.newProxyInstance(target1.getClass().getClassLoader(),
                target1.getClass().getInterfaces(),
                handler);
        System.out.println(target1.getClass());
        System.out.println(proxy1.getClass());
        proxy1.save();
    }

    @Test
    //通过代理工厂产生代理对象
    public void testDynamicProxyByFactory (){
        //需要代理的目标对象
        ISaveInfoDao target = new SaveInfoDao();
        ISaveInfoDao proxy = (ISaveInfoDao) new ProxyFactory(target).getProxyInstance();
        System.out.println(target.getClass());  //输出目标对象信息
        System.out.println(proxy.getClass());  //输出代理对象信息
        proxy.save();  //执行代理方法
    }
}

运行结果
在这里插入图片描述

参考博文:
https://segmentfault.com/a/1190000011291179
https://blog.csdn.net/yaomingyang/article/details/80981004

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值