• 【java学习—十四】java动态代理(6)



    问题:
    假设一个java项目有100个java类,每个java有10个方法,这总共有1000个方法,现在有这样一个需求,需要在每个java方法加上2句话:在方法执行前输出这个方法开始执行;在方法执行后输出这个方法已经完成。这么多方法不可能在每个方法中一一实现
    解决办法:动态代理

    1. 相关概念

    Proxy :专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态地生成实现类。

    创建一个动态代理类所对应的 Class 对象:
        static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h):直接创建一个动态代理对象

    2. 步骤

    1. 创建一个实现接口 InvocationHandler 的类,它必须实现 invoke方法,以完成代理的具体操作。
    2. 创建被代理的类以及接口
    3. 通过 Proxy 的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 创建一个 Subject 接口代理
    4. 通过 Subject 代理调用 RealSubject 实现类的方法

    3. 举例

    接口ITestDemo

    package day14;
    
    public interface ITestDemo {
    	void test1();
    	void test2();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    类TestDemoImpl实现接口ITestDemo

    package day14;
    
    public class TestDemoImpl implements ITestDemo {
    
    	@Override
    	public void test1() {
    		System.out.println("执行test1()方法");
    
    	}
    
    	@Override
    	public void test2() {
    		System.out.println("执行test2()方法");
    
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    动态代理类ProxyDemo

    package day14;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * 动态代理类
     * @author 14532
     *
     */
    public class ProxyDemo implements InvocationHandler{
    	
    	Object obj;//被代理的对象
    	
    	public ProxyDemo(Object obj) {
    		this.obj = obj;
    	}
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		
    		System.out.println(method.getName() + "方法开始执行");
    		
    		Object result = method.invoke(this.obj, args);//执行的是指定代理对象的指定方法
    		
    		System.out.println(method.getName() + "方法执行完毕");
    		
    		return null;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    Test.java:

    package day14;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    public class Test2 {
    	public static void main(String[] args) {
    		ITestDemo test = new TestDemoImpl();
    		/**
    		 * 注意:如果一个对象想要通过Proxy.newProxyInstance方法被代理
    		 * 那么这个对象的类一定要有相应的接口
    		 * 就像本类中的ITestDemo接口和实现类TestDemoImpl
    		 */
    		test.test1();
    		test.test2();
    		
    		System.out.println("=============下面执行动态代理================");
    		
    		/**
    		 * 需求:
    		 * 在执行test1和test2方法时需要加入一些东西
    		 * 在执行方法前打印test1或test2开始执行
    		 * 在执行方法后打印test1或test2执行完毕
    		 * 打印的方法名要和当时调用方法保持一致
    		 */
    		
    		InvocationHandler handler = new ProxyDemo(test);
    		
    		/**
    		 * Proxy.newProxyInstance(ClassLoader, interface, h)
    		 * 参数1是代理对象的类加载器
    		 * 参数2是被代理的对象的接口
    		 * 参数3是代理对象
    		 * 
    		 * 返回的值就是成功被代理后的对象,返回的是Object类型,需要根据当时情况去转换类型
    		 */
    		ITestDemo t= (ITestDemo)Proxy.newProxyInstance(handler.getClass().getClassLoader(), test.getClass().getInterfaces(), handler);
    		
    		t.test1();
    		System.out.println("----------------------------------");
    		t.test2();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    运行结果:

    在这里插入图片描述

    注意:如果一个对象想要通过Proxy.newProxyInstance方法被代理,那么这个对象的类一定要有相应的接口,就像本类中的ITestDemo接口和实现类TestDemoImpl

  • 相关阅读:
    LeetCode123
    【网络技术】计算机网络介绍
    ubuntu16.04部署nginx(无网络)
    nvm使用的注意事项和常用命令。
    【数据挖掘】2021年 Quiz 1-3 整理 带答案
    [持续更新]计算机经典面试题基础篇Day1
    用户上下文打通+本地缓存Guava
    PHP中的面向对象编程
    文件上传之中间件解析漏洞详解
    Qt5开发从入门到精通——第一篇(概述——(信号和槽机制)、(原对象系统)、(布局管理器))
  • 原文地址:https://blog.csdn.net/weixin_44883789/article/details/134416213