Java动态代理入门

一、案例准备、提出问题

  • 需求

    • 模拟某企业用户管理业务,需包含用户登录,用户删除,用户查询功能,并要统计每个功能的耗时
  • 分析

    • 定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,用户查询功能
    • 定义一个实现类UserServiceImpl实现UserService,并完成相关功能,且统计每个功能的耗时
    • 定义测试类,创建实现类方法,调用方法

UserService.java

/**
 * 模拟用户业务功能
 */
public interface UserService {
    String login(String loginName,String passWord);
    void selectUsers();
    boolean deleteUsers();
}

UserServiceImpl.java

public class UserServiceImpl implements UserService {
    @Override
    public String login(String loginName, String passWord) {
        long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(1000);
            if ("admin".equals(loginName) && "1234".equals(passWord)) {
                return "success";
            } else {
                return "fail";
            }
            } catch (Exception e)   {
            e.printStackTrace();
            return "error";
        } finally {
            long endTime = System.currentTimeMillis();
            System.out.println("login方法耗时:" + (endTime - startTime) / 1000.0 + "s");
        }
    }
    @Override
    public void selectUsers() {
        long startTime = System.currentTimeMillis();
        System.out.println("查询了100个用户的数据");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("select方法耗时:" + (endTime - startTime) / 1000.0 + "s");
    }
    @Override
    public boolean deleteUsers() {
        long startTime = System.currentTimeMillis();
        try {
            System.out.println("删除了100个用户的数据");
            Thread.sleep(500);
            return true;
        } catch (Exception e)   {
            e.printStackTrace();
            return false;
        } finally {
            long endTime = System.currentTimeMillis();
            System.out.println("delete方法耗时:" + (endTime - startTime) / 1000.0 + "s");
        }
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        System.out.println(userService.login("admin", "1234"));
        System.out.println(userService.deleteUsers());
        userService.selectUsers();
    }
}
  • 存在问题
    • 代码冗余
    • 逻辑不清晰

二、使用动态代理解决问题

  • 动态代理:代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能进行代理的。
  • 关键步骤
    • 必须有接口,实现类要实现接口(代理通常是基于接口实现的)
    • 创建一个实现类的对象,该对象为业务对象,紧接着为业务对象做一个代理对象

image-20220324111911276

UserService.java

/**
 * 模拟用户业务功能
 */
public interface UserService {
    String login(String loginName,String passWord);
    void selectUsers();
    boolean deleteUsers();
}

UserServiceImpl.java

public class UserServiceImpl implements UserService {
    @Override
    public String login(String loginName, String passWord) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if ("admin".equals(loginName) && "1234".equals(passWord)) {
                return "success";
            } else {
                return "fail";
        }
    }
    @Override
    public void selectUsers() {
        System.out.println("查询了100个用户的数据");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public boolean deleteUsers() {
        try {
            System.out.println("删除了100个用户的数据");
            Thread.sleep(500);
            return true;
        } catch (Exception e)   {
            e.printStackTrace();
            return false;
        }
    }
}

ProxyUtil.java

/**
 * 使用动态代理
 * public static Object newProxyInstance (ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
 * ClassLoader:类加载器,负责加载代理对象到内存中使用
 * Class<?>[]:被代理对象实现的全部接口,代理要为全部接口的全部方法进行代理
 * InvocationHandler:代理的核心处理逻辑
 */
public class ProxyUtil {
    /**
       生成业务对象的代理对象
     */
    public static UserService getProxy(UserServiceImpl obj) {
        // 返回了一个代理对象
        return (UserService) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // Object:代理对象本身
                        // Method:正在被代理的方法
                        // Object[]:被代理方法,应该传入的参数
                        long startTime = System.currentTimeMillis();
                        // 触发真正的业务功能
                        Object result = method.invoke(obj,args);
                        long endTime = System.currentTimeMillis();
                        System.out.println(method.getName() + "方法耗时:" + (endTime - startTime) / 1000.0 + "s");
                        // 把业务功能方法执行的结果返回给调用者
                        return result;
                    }
                });
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        // 1、把业务对象直接做成一个代理对象返回,代理对象的类型也是UserService类型
        UserService userService = ProxyUtil.getProxy(new UserServiceImpl());
        System.out.println(userService.login("admin", "1234"));
        System.out.println(userService.deleteUsers());
        userService.selectUsers();
    }
}
  • 动态代理的优点

    • 非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接口本身做代理
    • 可以为被代理对象的所有方法做代理
    • 可以在不改变方法源码的情况下,实现对方法功能的增强
    • 不仅简化了编程工作,提高了软件系统的可扩展性,同时也提高了开发效率
  • AOP切面编程思想

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值