zoukankan      html  css  js  c++  java
  • Java反射机制动态代理

    1.什么事反射机制动态代理

    在一段代码的前后动态执行其他操作,比如有一个方法是往数据库添加一个记录,我们可以通过动态代理,在操作数据库方法的前和后添加代码执行打开数据库连接和关闭数据库连接。

    2.演示

    学生管理类StudentManager.Class有三个方法,功能是新增一个学生数据addStudent(),删除一个学生数据deleteStudent(),
    获取当前时间getPersenterTime(),我通过动态代理实现,在addStudent()和deleteStudent()方法中我们在方法体的开头动态代理执行打开数据库的操作,在方法体的结尾我们动态代理关闭数据库连接的操作。

    为这三个方法定义接口规范 StudentService

    public interface StudentService {
        public void addStudent(String username);
        public void deleteStudent(String username);
        public String getPersentTime();
    }
    

    StudentManager.Class如下

    public class StudentManager implements StudentService {
        /**
         * 新增学生数据
         *
         * @param username
         */
        public void addStudent(String username) {
            System.out.println("在数据库中插入一条学生纪律");
        }
    
        /**
         * 删除学生数据
         *
         * @param username
         */
        public void deleteStudent(String username) {
            System.out.println("在数据库中删除一条学生纪律");
        }
    
        /**
         * 返回服务器当前时间
         *
         * @return
         */
        public String getPersentTime() {
            return "2018-07-30 3:30";
        }
    }
    

    添加方法拦截器StudentListener

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class StudentListener implements InvocationHandler {
        //代表需要代理的方法名
        private String methodsName = "addStudent,deleteStudent";
    
        public StudentListener(StudentManager manager) {
            this.manager = manager;
        }
    
        private StudentManager manager;
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (methodsName.contains(method.getName())) {
                //需要动态代理
                System.out.println("打开数据库链接");
                method.invoke(manager, args);
                System.out.println("关闭数据库链接");
            } else if (method.getName().equals("getPersentTime")) {
                //不需要动态代理,直接反射执行方法
                return method.invoke(manager, null);
            }
            return null;
        }
    }
    

    Proxy.newProxyInstance() 实现调用,也可以封装一下返回接口代理类方便调用。

    import java.lang.reflect.Proxy;
    
    public class Main {
        public static void main(String[] args) {
            StudentManager studentManager = new StudentManager();
            Class clazz = studentManager.getClass();
            StudentListener listener = new StudentListener(studentManager);
    
            StudentService serviceProxy = (StudentService) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), listener);
            serviceProxy.addStudent("张三");
            System.out.println("------------------------");
            serviceProxy.deleteStudent("李四");
            System.out.println("------------------------");
            System.out.println("时间:" + serviceProxy.getPersentTime());
        }
    }
    

    输出结果如下:
    image.png

  • 相关阅读:
    LOJ6433 [PKUSC2018] 最大前缀和 【状压DP】
    [NOIP2017] 宝藏 【树形DP】【状压DP】
    51Nod1824 染色游戏 【Lucas定理】【FMT】【位运算】
    51Nod1778 小Q的集合 【组合数】【Lucas定理】
    LOJ6436 [PKUSC2018] 神仙的游戏 【FFT】
    LOJ6432 [PKUSC2018] 真实排名 【组合数】
    BZOJ5210 最大连通子块和 【树链剖分】【堆】【动态DP】
    LOJ2269 [SDOI2017] 切树游戏 【FWT】【动态DP】【树链剖分】【线段树】
    洛谷3707 [SDOI2017] 相关分析 【线段树】
    RBAC
  • 原文地址:https://www.cnblogs.com/chenyangqi/p/9391467.html
Copyright © 2011-2022 走看看