zoukankan      html  css  js  c++  java
  • java中动态反射

    java中动态反射能达到的效果和python的语法糖很像,能够截获方法的实现,在真实方法调用之前和之后进行修改,甚至能够用自己的实现进行特别的替代,也可以用其实现面向切片的部分功能。动态代理可以方便实现AOP,AOP将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面Crosscutting enterprise concerns,例如,所有大中型应用都要涉及到的持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging)等。

    JDK默认的动态代理机制基于interface,而使用CGLib可以实现对类的动态代理功能。JDK动态代理机制涉及到几个地方:

      (1) Proxy类

          Proxy类提供了用于创建动态代理类和实例对象的方法,它是所创建的动态代理类的父类,它最常用的方法如下:

    • public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces):该方法用于返回一个Class类型的代理类,在参数中需要提供类加载器并需要指定代理的接口数组(与真实主题类的接口列表一致)。
    • public static Object newProxyInstance(ClassLoader loader, Class<?>[]interfaces, InvocationHandler h):该方法用于返回一个动态创建的代理类的实例,方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示代理类所实现的接口列表(与真实主题类的接口列表一致),第三个参数h表示所指派的调用处理程序类。

       (2) InvocationHandler接口

          InvocationHandler接口是代理处理程序类的实现接口,该接口作为代理实例的调用处理者的公共父类,每一个代理类的实例都可以提供一个相关的具体调用处理者(InvocationHandler接口的子类)。在该接口中声明了如下方法:

    • public Object invoke(Objectproxy, Method method, Object[] args):该方法用于处理对代理类实例的方法调用并返回相应的结果,当一个代理实例中的业务方法被调用时将自动调用该方法。invoke()方法包含三个参数,其中第一个参数proxy表示代理类的实例,第二个参数method表示需要代理的方法,第三个参数args表示代理方法的参数数组。

            动态代理类需要在运行时指定所代理真实主题类的接口,客户端在调用动态代理对象的方法时,调用请求会将请求自动转发给InvocationHandler对象的invoke()方法,由invoke()方法来实现对请求的统一处理。

    下面的这个例子,在每个方法前后分别打印日志,说明该方法开始执行,在改方法结束的时候打印日志方法结束。如果不采用动态代理机制,则需要在每个方法的开始和结束的位置都加上类似的日志,有了代理机制以后只用一句话。

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    interface TestInterface {
    	void print(String p);
    
    	void filter();
    
    	void say(String string);
    }
    
    class TestImpl implements TestInterface {
    
    	public void say(String to) {
    		System.out.println("Say hello to " + to);
    	}
    
    	public void print(String s) {
    		System.out.println("print : " + s);
    	}
    
    	public void filter() {
    		System.out.println("filter");
    	}
    }
    
    class LogHandler implements InvocationHandler {
    	private Object dele;
    
    	public LogHandler(Object obj) {
    		this.dele = obj;
    	}
    
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		String funcname = method.getName();
    		// 这里过滤掉filter方法,什么都不做
    		if (method.getName().equals("filter")) {
    			System.out.println(method.getName() + " filter,not execute");
    			return null;
    		}
    		beforeFunction(funcname);
    		Object result = method.invoke(dele, args);
    		endFunction(funcname);
    		return result;
    	}
    
    	private void beforeFunction(String funcname) {
    		System.out.println("method:" + funcname + " begins.");
    	}
    
    	private void endFunction(String funcname) {
    		System.out.println("method:" + funcname + " ends.");
    	}
    }
    
    public class ProxyTest {
    
    	public static void main(String[] args) {
    		TestImpl impl = new TestImpl();
    		LogHandler handler = new LogHandler(impl);
    		// 这里把handler与impl新生成的代理类相关联
    		TestInterface testinter = (TestInterface) Proxy.newProxyInstance(impl.getClass().getClassLoader(),
    				impl.getClass().getInterfaces(), handler);
    		// 这里无论访问哪个方法,都是会把请求转发到handler.invoke
    		testinter.print("All the test");
    		testinter.say("Cob");
    		// 这里过滤掉filter方法,什么都不返还
    		testinter.filter();
    	}
    
    }
    

      

  • 相关阅读:
    Spring boot和Spring cloud对应版本兼容问题
    关于 Workbench中 pk,nn,uq,bin,un,zf,ai 的解释
    WebServiceUtil
    POI 导出Excel工具类
    初步了解HTTP协议
    性能测试从零开始-LoadRunner入门
    创新券功能介绍
    Loadrunner 11安装和破解
    《追风筝的人》读后感
    h5学习-webstorm工具的激活
  • 原文地址:https://www.cnblogs.com/laodageblog/p/java.html
Copyright © 2011-2022 走看看