• 【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

  • 相关阅读:
    c#使用自带库对字符串进行AES加密、解密
    ES6新特性
    〖Python网络爬虫实战㊲〗- JavaScript 逆向实战(一)
    Java学习笔记2024/2/20
    C#控制台贪吃蛇
    危!苹果提出上诉,App Store 调整或将推迟数年
    【Bun1.0】使用 Bun.js 构建快速、可靠和安全的 JavaScript 应用程序
    RK3568 GPIO 按键事件响应
    【LeetCode】 贴纸拼词(动态规划)
    Netty selector的运行
  • 原文地址:https://blog.csdn.net/weixin_44883789/article/details/134416213