Java动态代理--思想

动态代理

案例引入

  • 需求

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

  • 分析

    定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,用户查询功能。

    定义一个实现类UserServiceImpl实现UserService,并完成相关功能,且统计每个功能的耗时。

    定义测试类,创建实现类对象,调用方法。

示例代码

/*
    模拟用户业务功能
 */
public interface UserService {
    String login(String username,String password);
    void findUser();
    boolean removeUser();
}

public class UserServiceImpl implements UserService{
    @Override
    public String login(String username, String password) {
        long startTime = System.currentTimeMillis();
        try{
            Thread.sleep(1000);
            if ("admin".equals(username) && "123".equals(password)) {
                return "success";
            }
            return "用户名或密码有误";
        }catch (Exception e){
            e.printStackTrace();
            return "error";
        }finally {
            long endTime = System.currentTimeMillis();
            System.out.println("login 花费了:"+(endTime-startTime)/1000+"s");
        }
    }

    @Override
    public void findUser() {
        long startTime = System.currentTimeMillis();
        System.out.println("找到300个用户信息");
        try{
            Thread.sleep(2000);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            long endTime = System.currentTimeMillis();
            System.out.println("findUser 花费了:"+(endTime-startTime)/1000+"s");
        }
    }

    @Override
    public boolean removeUser() {
        long startTime = System.currentTimeMillis();
        System.out.println("删除 300个用户信息");
        try{
            Thread.sleep(500);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }finally {
            long endTime = System.currentTimeMillis();
            System.out.println("removeUser 花费了:"+(endTime-startTime)/1000+"s");
        }
    }
}

public class Test {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        System.out.println(userService.login("admin","123"));
        System.out.println(userService.removeUser());
        userService.findUser();
    }
}

案例存在问题

  • 每个方法都要进行性能统计
  • 大量重复的代码

解决案例问题–动态代理

什么是动态代理

​ 代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理的

动态代理关键步骤

  1. 必须有接口,实现类要实现接口(代理通常是基于接口实现的)。
  2. 创建一个实现类的对象,该对象为业务对象,紧接着为业务对象做一个代理对象。

Java动态代理--思想_第1张图片

示例代码

/*
    模拟用户业务功能
 */
public interface UserService {
    String login(String username,String password);
    void findUser();
    boolean removeUser();
}
public class UserServiceImpl implements UserService{
    @Override
    public String login(String username, String password) {
        try{
            Thread.sleep(1000);
            if ("admin".equals(username) && "123".equals(password)) {
                return "success";
            }
            return "用户名或密码有误";
        }catch (Exception e){
            e.printStackTrace();
            return "error";
        }
    }

    @Override
    public void findUser() {
        System.out.println("找到300个用户信息");
        try{
            Thread.sleep(2000);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public boolean removeUser() {
        System.out.println("删除 300个用户信息");
        try{
            Thread.sleep(500);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
}


PRoxyUtil 动态代理工具类

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

/*
    public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
    参数:
        参数一:类加载器,负责加载代理类到内存中使用
        参数二:获取被代理的对象实现的全部接口,代理腰围全部接口的 全部方法进行代理
        参数三:代理的核心处理逻辑
 */
public class ProxyUtil {
    /*
        生成业务对象的代理对象
        @param userService
        @return
     */
    public static UserService getProxy(UserServiceImpl userService) {
        // 返回了一个代理对象
        return (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces()
                , new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 参数一: 代理对象本身
                        // 参数二: 正在被代理的方法
                        // 参数三: 被代理方法应传入的参数
                        long startTime = System.currentTimeMillis();
                        // 马上触发方法的真正执行(触发真正的业务功能)
                        Object res = method.invoke(userService, args);
                        long endTime = System.currentTimeMillis();
                        System.out.println("removeUser 花费了:"+(endTime-startTime)/1000+"s");
                        // 把业务动能方法执行的结构返回给调用者
                        return res;
                    }
                });
    }
}

Test 测试类

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

动态代理的优点

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

任意接口的实现类做做代理代码示例

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

/*
    public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
    参数:
        参数一:类加载器,负责加载代理类到内存中使用
        参数二:获取被代理的对象实现的全部接口,代理腰围全部接口的 全部方法进行代理
        参数三:代理的核心处理逻辑
 */
public class ProxyUtil {
    /*
        生成业务对象的代理对象
        @param userService
        @return
     */
    public static  T getProxy(T obj) {
        // 返回了一个代理对象
        return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces()
                , new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 参数一: 代理对象本身
                        // 参数二: 正在被代理的方法
                        // 参数三: 被代理方法应传入的参数
                        long startTime = System.currentTimeMillis();
                        // 马上触发方法的真正执行(触发真正的业务功能)
                        Object res = method.invoke(obj, args);
                        long endTime = System.currentTimeMillis();
                        System.out.println("removeUser 花费了:"+(endTime-startTime)/1000+"s");
                        // 把业务动能方法执行的结构返回给调用者
                        return res;
                    }
                });
    }
}

= System.currentTimeMillis();
System.out.println(“removeUser 花费了:”+(endTime-startTime)/1000+“s”);
// 把业务动能方法执行的结构返回给调用者
return res;
}
});
}
}


你可能感兴趣的:(java,开发语言,junit)