栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java静态代理和动态代理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java静态代理和动态代理

文章目录
  • 一、静态代理
    • 例子
  • 二、动态代理
    • 1. JDK动态代理

参考: Java 动态代理详解

一、静态代理

实现静态代理分三步:

  1. 主题抽象类或者接口
  2. 真实对象实现接口方法
  3. 代理对象实现接口,代理主题
例子

假设要对一个service进行前后通知,先创建UserService主题接口

  1. 编写UserService主题
package com.yzx.proxy;

public interface UserService {

    void select();

    void update();

}
  1. 编写真实对象实现主题接口
package com.yzx.proxy;

public class UserServiceImpl implements UserService{
    @Override
    public void select() {
        System.out.println("查询数据");
    }

    @Override
    public void update() {
        System.out.println("更新数据");
    }
}

  1. 编写代理类对UserService进行增强
package com.yzx.proxy;

public class UserServiceProxy implements UserService{

    private UserService userService;

    public UserServiceProxy(UserService userService){
        this.userService = userService;
    }

    @Override
    public void select() {
        System.out.println("我要准备查询数据了");
        userService.select();
        System.out.println("查询数据完成");
    }

    @Override
    public void update() {
        System.out.println("我要准备更新数据了");
        userService.update();
        System.out.println("更新数据完成");
    }
}
  1. 客户端测试
package com.yzx.proxy;

public class Client01 {

    public static void main(String[] args) {
        UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
        proxy.select();
        proxy.update();
    }

}

输出

从结果可看出已经对真实对象进行了增强,并且对真实对象代码没有任何修改,这就是静态代理的一个好处。

但是仔细想想假如我要对多个类进行增强,使用静待代理解决的话有两种方式:

  1. 使用一个代理类、里面写多个接口,缺点是代理类会变的很庞大,里面接口过多。
  2. 使用多个代理类,每个代理类对一个类进行增强。缺点是代理类会很多。
    并且当主题接口要添加方法,删除方法时,代理类,真实对象类都要修改,这样维护会很麻烦。

要解决上面的问题就要使用到动态代理。

二、动态代理

两种常见的动态代理技实现:

  1. 通过实现接口的方式,JDK动态代理
  2. 通过继承的方式,CGLIB动态代理
1. JDK动态代理

jdk动态代理主要涉及到两个类:java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler

编写一个实现InvocationHandler调用逻辑处理器LogHandler类,提供日志增强功能;在LogHandler中维护一个目标对象;在invoke方法中编写调用方法的处理逻辑;

package com.yzx.proxy;

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

public class LogHandler implements InvocationHandler {

    Object object;

    public LogHandler(Object object){
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(object, args);
        after();
        return result;
    }

    private void before(){
        System.out.println("前置通知");
    }

    private void after(){
        System.out.println("后置通知");
    }
}

编写客户端,获取动态生成的代理类的对象须使用Proxy的newProxyInstance方法,具体步骤可见代码和注释

import proxy.UserService;
import proxy.UserServiceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client2 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        // 设置变量可以保存动态代理类,默认名称以 $Proxy0 格式命名
        // System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        // 1. 创建被代理的对象,UserService接口的实现类
        UserServiceImpl userServiceImpl = new UserServiceImpl();
        // 2. 获取对应的 ClassLoader
        ClassLoader classLoader = userServiceImpl.getClass().getClassLoader();
        // 3. 获取所有接口的Class,这里的UserServiceImpl只实现了一个接口UserService,
        Class[] interfaces = userServiceImpl.getClass().getInterfaces();
        // 4. 创建一个将传给代理类的调用请求处理器,处理所有的代理对象上的方法调用
        //     这里创建的是一个自定义的日志处理器,须传入实际的执行对象 userServiceImpl
        InvocationHandler logHandler = new LogHandler(userServiceImpl);
        
        UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, logHandler);
        // 调用代理的方法
        proxy.select();
        proxy.update();
        
        // 保存JDK动态代理生成的代理类,类名保存为 UserServiceProxy
        // ProxyUtils.generateClassFile(userServiceImpl.getClass(), "UserServiceProxy");
    }
}

输出结果

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/344930.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号