java之动态代理

静态代理与动态代理的区别

动态代理的角色和静态代理的一样 .
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
基于接口的动态代理----JDK动态代理
基于类的动态代理–cglib
现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist
我们这里使用JDK的原生代码来实现,其余的道理都是一样的!

动态代理制反射 Method

Method类表示方法,类中的方法,通过Method可以执行某个方法
接口

public interface StudentsService {
    /**
     * 获取用户名
     * @return
     */
    String getName();

    /**
     * 获取年龄
     * @return
     */
    Integer getAge(Integer age);

    void getNameAndAge(String name,Integer age);
}

实现类

public class UserServiceImpl implements UserService,StudentsService{
    @Override
    public String getName() {
        System.out.println("getName");
        return "getName";
    }

    @Override
    public Integer getAge(Integer age) {
        System.out.println("获得年龄:"+age);
        return age;
    }

    @Override
    public void getNameAndAge(String name, Integer age) {
        System.out.println(name + "的年龄为:" + age);
    }
}
    @Test
    public void getMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        UserServiceImpl userService = new UserServiceImpl();
        Method getName = userService.getClass().getMethod("getName");
        Object invoke = getName.invoke(userService);
        System.out.println(invoke);
    }
    @Test
    public void getAge() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        UserServiceImpl userService = new UserServiceImpl();
        Method getName = userService.getClass().getMethod("getAge", Integer.class);
         // 通过method可以执行getAge的方法的调用
        /**
         * 表示执行方法的调用
         * 参数1: 表示对象,要执行这个对象的xxx方法
         * 参数2: 方法的参数
         * 返回值: Object表示方法执行后的返回值
         */
        Object invoke = getName.invoke(userService,25);
        System.out.println(invoke);
    }

    @Test
    public void getNameAndAge() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        UserServiceImpl userService = new UserServiceImpl();
        Method getNameAndAge = userService.getClass().getMethod("getNameAndAge", String.class, Integer.class);
        // 输出:fangqing的年龄为:24
        getNameAndAge.invoke(userService,"fangqing",24);
    }

InvocationHandler (调用处理器)

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}
  • invoke()表示代理对象要执行的功能代码
  • 你的代理类要完成的功能就写在invoke()方法中
  • 代理类可以调用目标方法,增强功能
    参数
  • Object proxy : jdk创建的代理对象,无需赋值
  • 目标类中的方法 , jdk提供的method对象
  • 目标类中的方法参数 ,jdk提供

反射包核心类Proxy

作用:创建代理对象
方法:静态方法: newProxyInstance
参数

  • ClassLoader loader : 类加载器,负责向内存中加载对象的
    • 使用反射获取对象的 ClassLoader
    • 比如有一个类a , a.getClass().getClassLoader()
    • 这个是目标对象的类加载器
  • Class<?>[] interfaces : 目标所实现的接口,也是通过反射获取的
  • InvocationHandler h : 我们自己写的,代理类要完成的功能
  • 返回值就是代理对象

demo实现

用户接口实现增删

public interface UserService {
    /**
     * 新增
     */
    void add();
    /**
     * 删除
     */
    void delete();
}

用户接口实现类

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("add");
    }

    @Override
    public void delete() {
        System.out.println("delete");
    }
}

通用代理类,实现InvocationHandler

public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;
    // 目标对象是活动的,不是固定的谁传就给谁代理
    public void setTarget(Object target) {
        this.target = target;
    }
    // 创建代理类
    public Object getProxy() {
    //        类加载器为:sun.misc.Launcher$AppClassLoader@b4aac2
//        代理接口为:[Ljava.lang.Class;@15a1588
//        调用处理器为:com.example.动态代理.ProxyInvocationHandler@1116ca2
    	System.out.println("类加载器为:"+this.getClass().getClassLoader());
        System.out.println("代理接口为:"+target.getClass().getInterfaces());
        System.out.println("调用处理器为:"+ this);
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
    // 通过代理对象调用功能方法时,便会执行此方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 功能增强
        log(method.getName());
        // 调用目标对象的方法
        Object result = method.invoke(target,args);
        return result;
    }
    public void log(String methodName){
        System.out.println("执行了" + methodName + "方法");
    }
}
    @Test
    public void test() {
        UserServiceImpl userServiceImpl = new UserServiceImpl();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        proxyInvocationHandler.setTarget(userServiceImpl);
        UserService proxy = (UserService) proxyInvocationHandler.getProxy();
        proxy.add();
        // 输出结果为:
        //类加载器为:sun.misc.Launcher$AppClassLoader@b4aac2
		//代理接口为:[Ljava.lang.Class;@15a1588
		//调用处理器为:com.example.动态代理.ProxyInvocationHandler@1116ca2
		//执行了add方法
		//add
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值