Java基础-动态代理


※ 学习目标

  • 为什么需要代理?
  • 代理长什么样子?
  • Java通过什么来保证代理的样子?
  • Java提供了什么API帮助我们创建代理?
  • newProxyInstance方法在创建代理时,需要接几个参数,每个参数的含义?
  • 通过InvocationHandler的invoke方法指定的代理时,这个invoke会被谁调用,要接几个参数?

一、为什么需要设置代理

对象如果嫌身上的事太多,可以通过代理来转移部分责任。
对象有什么方法想被代理,代理就一定要有对应的方法。

二、如何创建代理

创建唱歌跳舞的对象

public class BigStart implements Start{
    private String name;

    public BigStart(String name) {
        this.name = name;
    }

    public String sing(String name) {
        System.out.println(this.name + "正在唱:" + name);
        return "谢谢!谢谢!";
    }

    public void dance() {
        System.out.println(this.name + "正在跳舞!!!");
    }
}

创建代理接口

public interface Start {
    String sing(String name);

    void dance();
}

创建代理工具类

public class ProxyUtil {
    public static Start createProxy(BigStart bigStart) {

        Start startProxy = (Start) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{Start.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 代理对象业务逻辑
                        if (method.getName().equals("sing")) {  // 唱歌
                            System.out.println("准备话筒,收钱20万!!!");
                        } else if (method.getName().equals("dance")) {  // 跳舞
                            System.out.println("准备场地,收钱10000万!!!");
                        }
                        return method.invoke(bigStart, args);
                    }
                });

        return startProxy;
    }
}

执行代理测试

public class Test {
    public static void main(String[] args) {
        // 创建类
        BigStart bigStart = new BigStart("杨超越");

        // 创建类的代理对象
        Start startProxy = ProxyUtil.createProxy(bigStart);

        // 执行方法
        String sing = startProxy.sing("好日子");
        System.out.println(sing);

        startProxy.dance();
    }
}

总结

 // 创建代理对象
 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
参数说明
ClassLoader loader指定类加载器【当前类的加载器】 类.class.getClassLoader()
Class<?>[] interfaces生成的代理长什么样子【接口数组】
InvocationHandler h指定生成的代理对象要做什么
// 代理对象实现逻辑
public Object invoke(Object proxy, Method method, Object[] args)
参数说明
Object proxy代理对象
Method method代理方法
Object[] args传递的参数

三、实际应用

  • UserService
public interface UserService {
    /**
     * 登录功能
     *
     * @param loginName 用户名
     * @param passWorld 密码
     */
    void login(String loginName, String passWorld) throws Exception;

    /**
     * 删除用户
     */
    void deleteUsers() throws Exception;

    /**
     * 查询用户
     *
     * @return 返回数组的格式
     */
    String[] selectUsers() throws Exception;
}
  • UserServiceImpl
public class UserServiceImpl implements UserService {
    @Override
    public void login(String loginName, String passWorld) throws Exception {
        // long startTime = System.currentTimeMillis();

        if ("root".equals(loginName) && "root".equals(passWorld)) {
            System.out.println("登录成功,欢迎使用本系统!!!");
        } else {
            System.out.println("登录失败,用户名或密码错误!!!");
        }
        Thread.sleep(1000);

//        long endTime = System.currentTimeMillis();
//        System.out.println("login方法执行耗时:" + (endTime - startTime) / 1000.0 + "s");
    }

    @Override
    public void deleteUsers() throws Exception {
//        long startTime = System.currentTimeMillis();

        System.out.println("成功删除了1万个用户~");
        Thread.sleep(1000);

//        long endTime = System.currentTimeMillis();
//        System.out.println("deleteUsers方法执行耗时:" + (endTime - startTime) / 1000.0 + "s");
    }

    @Override
    public String[] selectUsers() throws Exception {
//        long startTime = System.currentTimeMillis();

        System.out.println("查询出了3个用户~");
        String[] names = {"张三", "李四", "王五"};
        Thread.sleep(1000);

//        long endTime = System.currentTimeMillis();
//        System.out.println("selectUsers方法执行耗时:" + (endTime - startTime) / 1000.0 + "s");
        return names;
    }
}
  • ProxyUtil
public class ProxyUtil {
    public static UserService createProxy(UserService userService) {
        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
                new Class[]{UserService.class}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        if (method.getName().equals("login") || method.getName().equals("deleteUsers") || method.getName().equals("selectUsers")) {
                            long startTime = System.currentTimeMillis();

                            // 执行方法
                            Object invoke = method.invoke(userService, args);

                            long endTime = System.currentTimeMillis();
                            System.out.println(method.getName() + "方法执行耗时:" + (endTime - startTime) / 1000.0 + "s");
                            return invoke;
                        } else {
                            return method.invoke(userService, args);
                        }

                    }
                });
        return userServiceProxy;
    }
}
  • Test
public class Test {
    public static void main(String[] args) throws Exception {
        // 1. 创建用户业务类对象
//        UserService userService = new UserServiceImpl();
        UserService userServiceProxy = ProxyUtil.createProxy(new UserServiceImpl());

        // 2. 登录功能
        userServiceProxy.login("root", "root");
        System.out.println("--------------------------------------------------");

        // 3. 删除用户
        userServiceProxy.deleteUsers();
        System.out.println("--------------------------------------------------");

        // 4. 查询用户
        userServiceProxy.selectUsers();
        System.out.println("--------------------------------------------------");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Monly21

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值