`

Java基础十:JDK 动态代理类分析(java.lang.reflect.Proxy使用)

阅读更多
/**
 * JDK 动态代理类分析(java.lang.reflect.Proxy使用)
 * 
 * @author 张明学
 * 
 */
public class ProxyStudy {
	
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
		// 动态代理类:通用指定类加载器,和接口产生一类
		// getProxyClass()返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。
		Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		System.out.println("动态产生的类名为:" + clazzProxy.getName());
		System.out.println("----------获取动态产生的类的构造方法---------");
		Constructor[] constructors = clazzProxy.getConstructors();
		int i = 1;
		for (Constructor constructor : constructors) {
			System.out.println("第" + (i++) + "个构造方法名:" + constructor.getName());
			Class[] parameterClazz = constructor.getParameterTypes();
			System.out.println("第" + (i++) + "个构造方法参数:" + Arrays.asList(parameterClazz));
		}
		System.out.println("----------获取动态产生的类的普通方法---------");
		Method[] methods = clazzProxy.getDeclaredMethods();
		for (int j = 0; j < methods.length; j++) {
			Method method = methods[j];
			System.out.println("第" + (j + 1) + "个普通方法名:" + method.getName());
			Class[] parameterClazz = method.getParameterTypes();
			System.out.println("第" + (j + 1) + "个普通方法参数:" + Arrays.asList(parameterClazz));
		}
		System.out.println("---------获取动态代理对象的构造方法---------");
		// 动态代理产生的对象的构造方法需要一个实现java.lang.reflect.InvocationHandler接口的对象,故不能通过
		// clazzProxy.newInstance();产生一个对象,可以根据构造方法产生一个对象
		// InvocationHandler 是代理实例的调用处理程序 实现的接口。
		Constructor constructor = clazzProxy.getConstructor(InvocationHandler.class);

		// 代理产生的对象
		Collection proxyBuildCollection = (Collection) constructor
				.newInstance(new InvocationHandler() {
					// 为什么这里选择ArrayList作为目标对象?
					// 因为这里的constructor是clazzProxy这个动态类的构造方法,clazzProxy是通过Proxy.getProxyClass()方法产生的,
					// 该方法有两个参数,一个是指定类加载器,一个是指定代理要实现的接口,这个接口我上面指定了Collection
					// 而ArrayList实现了Collection接口,固可以为该动态类的目标对象
					ArrayList target = new ArrayList();// 动态类的目标对象

					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						System.out.println("执行目标" + method.getName() + "方法之前:"
								+ System.currentTimeMillis());
						Object result = method.invoke(target, args);// 其实代理对象的方法调用还是目标对象的方法
						System.out.println("执行目标" + method.getName() + "方法之后:"
								+ System.currentTimeMillis());
						return result;
					}

				});
		proxyBuildCollection.clear();
		proxyBuildCollection.add("abc");
		proxyBuildCollection.add("dbc");
		System.out.println(proxyBuildCollection.size());
		System.out.println(proxyBuildCollection.getClass().getName());
		
		/**
		 * 动态代理:总结如下:
		 * 1,通过Proxy.getProxyClass(classLoader,interface)方法产生一个动态类的class字节码(clazz)
		 *    该getProxyClass()方法有两个参数:一个是指定该动态类的类加载器,一个是该动态类的要实现的接口(从这里可以看现JDK的动态代理必须要实现一个接口)
		 *    
		 * 2,通过第一步的获取的clazz对象可以获取它的构造方法constructor,那么就可以通用constructor的newInstance()方法构造出一个动态实体对象
		 *    但constructor的newInstance()方法需要指定一个实现了InvocationHandler接口的类handler,在该类中需要一个目标对象A和实现invoke方法
		 *    目标对象A要求能对第一步中的接口的实现,因为在invoke方法中将会去调用A中的方法并返回结果。
		 *    过程如下:调用动态代理对象ProxyObject的x方法 ————> 进入构造方法传进的handler的invoke方法 ————> invoke方法调用handler中的target对象
		 *    	      的x方法(所以要求target必须要实现构造动态代理类时指定的接口)并返回它的返回值。(其实如果我们代理P类,那么target就可以选中P类,只是要求P必需实现一个接口)
		 *    
		 *    那么上述中x方法有哪些呢?除了从Object继承过来的方法中除toString,hashCode,equals外的方法不交给handler外,其它的方法全部交给handler处理
		 *    如上面proxyBuildCollection.getClass().getName()就没有调用handler的getClass方法,而是调用自己的
		 *    
		 * 3,在handler的invoke方法中return method.invoke(target,args)就是将方法交给target去完成。那么在这个方法执行之前,之后,异常时我们都可以做一些操作,
		 *    并且可以在执行之前检查方法的参数args,执行之后检查方法的结果
		 */
		System.out.println("-------------------下面的写法更简便--------------------");
		
		// proxyBuildColl是对ArrayList进行代理
		Collection proxyBuildCollection2 = (Collection) Proxy.newProxyInstance(
				Collection.class.getClassLoader(),// 指定类加载器
				new Class[] { Collection.class },// 指定目标对象实现的接口
				// 指定handler
				new InvocationHandler() {
					ArrayList target = new ArrayList();

					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						System.out.println(method.getName() + "执行之前...");
						if (null != args) {
							System.out.println("方法的参数:" + Arrays.asList(args));
						} else {
							System.out.println("方法的参数:" + null);
						}
						Object result = method.invoke(target, args);
						System.out.println(method.getName() + "执行之后...");
						return result;
					}
				});
		proxyBuildCollection2.add("abc");
		proxyBuildCollection2.size();
		proxyBuildCollection2.clear();
		proxyBuildCollection2.getClass().getName();
		
		System.out.println("-------------------对JDK动态代理的重构--------------------");
		Set proxySet = (Set) buildProxy(new HashSet(), new MyAdvice());
		proxySet.add("abc");
		proxySet.size();
	}
	/**
	 * 构造一个目标对象的代理对象
	 * 
	 * @param target
	 *            目标对象(需要实现某个接口)
	 * @return
	 */
	public static Object buildProxy(final Object target,final AdviceInter advice) {
		Object proxyObject = Proxy.newProxyInstance(
				target.getClass().getClassLoader(),// 指定类加载器
				target.getClass().getInterfaces(), // 指定目标对象实现的接口
				// handler
				new InvocationHandler() {
					
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						advice.beforeMethod(target, method, args);
						Object result = method.invoke(target, args);
						advice.afterMethod(target, method, args);
						return result;
					}
				});
		return proxyObject;
	}
	
}

 

/**
 * 代理中执行目标方法之前之后的操作的一个实例
 * 
 * @author 张明学
 * 
 */
public class MyAdvice implements AdviceInter {

	public void afterMethod(Object target, Method method, Object[] args) {
		System.out.println("目标对象为:" + target.getClass().getName());
		System.out.println(method.getName() + "执行完毕!");
	}

	public void beforeMethod(Object target, Method method, Object[] args) {
		System.out.println(method.getName() + "开始执行");
		if (null != args) {
			System.out.println("参数为:" + Arrays.asList(args));
		} else {
			System.out.println("参数为:" + null);
		}
	}
}

 

/**
 * 代理中执行目标方法之前之后的操作
 * 
 * @author 张明学
 * 
 */
public interface AdviceInter {
	/**
	 * 目标方法执行之前
	 * 
	 */
	public void beforeMethod(Object target, Method method, Object[] args);

	/**
	 * 目标方法执行之后
	 * 
	 * @param target
	 *            目标对象
	 * @param method
	 *            方法
	 * @param args
	 *            参数
	 */
	public void afterMethod(Object target, Method method, Object[] args);
}

 

分享到:
评论
2 楼 dd_zhuang 2011-12-21  
写的很好
1 楼 zenghaijun 2011-09-27  
顶 说的很详细 不错呀

相关推荐

    基于java的企业级应用开发:JDK动态代理.ppt

    首先,JDK动态代理是通过`java.lang.reflect.Proxy`类来实现的。这个类提供了创建动态代理对象的能力,允许我们为已经存在的接口实现动态生成的代理类。在Spring框架中,当我们的目标对象实现了至少一个接口时,...

    java设计模式【之】JDK动态代理【源码】【场景:帮爸爸买菜】.rar

    * 动态代理中的静态方法:java.lang.reflect.Proxy.newProxyInstance (ClassLoader(类加载器),interface(接口),handler(监听处理器)) * * 代码示例:《帮爸爸买菜》 * 1.Father: 被代理类,必须需要实现接口 ...

    java 请求的方法不存在(NoSuchMethodException)

    3. **动态代理**:在使用Java动态代理生成的代理类中,如果尝试调用的目标接口方法不存在,同样会导致异常。 二、常见场景 1. **类加载顺序**:在多模块项目中,类加载顺序可能影响到方法的查找,如果依赖的类或...

    java动态代理(JDK和cglib)共10页.pdf.z

    Java动态代理是Java编程中一个重要的特性,它允许我们在运行时创建代理类,这些代理类可以作为原有类的代理,实现在调用原有方法前后添加额外的功能,如日志记录、事务管理、性能监控等。Java提供了两种主要的动态...

    java动态代理(JDK和cglib).pdf

    JDK动态代理的核心类是`java.lang.reflect.Proxy`和`java.lang.reflect.InvocationHandler`。`Proxy`类用于创建动态代理实例,而`InvocationHandler`接口定义了一个处理代理对象方法调用的回调方法`invoke()`。 ...

    java jdk 动态代理 演示demo

    Java JDK提供了`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口,它们是实现动态代理的关键组件。`Proxy`类用于创建代理对象,而`InvocationHandler`接口定义了一个方法,用于处理代理对象...

    模拟JDK动态代理

    JDK动态代理是通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现的。Proxy类提供了创建动态代理对象的方法,而InvocationHandler接口定义了处理代理对象方法调用的逻辑。 ### 2. ...

    jdk动态代理使用[文].pdf

    在Java编程中,JDK动态代理是一种强大的工具,它允许我们在运行时创建代理类来拦截对目标对象的调用,从而实现额外的功能,比如日志记录、性能监控、事务管理等,而无需修改原始代码。这里我们将深入探讨JDK动态代理...

    JDK动态代理_JDK动态代理

    - **`java.lang.reflect.Proxy`**:提供了创建动态代理类和实例的方法。通过`newProxyInstance`方法,传入ClassLoader、接口数组和InvocationHandler实例,即可创建一个动态代理对象。 - **`java.lang.reflect....

    java动态代理(JDK和cglib)共10页.pdf.zip

    JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。Proxy类用于创建代理实例,而InvocationHandler接口定义了调用处理程序,它在代理对象的方法被调用时介入执行。 1...

    java jdk 动态代理演示demo

    首先,`java.lang.reflect.Proxy`是用于生成动态代理类的类。它提供了一个静态方法`newProxyInstance()`,这个方法接收三个参数:一个类加载器、一个接口数组和一个`InvocationHandler`实例。类加载器用于加载生成的...

    JDK动态代理proxy

    JDK动态代理,全称为Java Dynamic Proxy,是Java标准库提供的一种强大且灵活的机制,允许我们在运行时创建代理类来实现指定的接口。这种机制主要用于实现AOP(面向切面编程)或为已有接口提供额外的功能,如日志、...

    java 动态代理实例(JDK代理与CGLIB代理)

    **JDK代理**是基于接口的代理,它通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。当我们的目标对象实现了特定的接口时,我们可以使用JDK动态代理来创建该对象的代理。以下是JDK...

    浅谈JDK动态代理与CGLIB代理去区别

    首先,JDK动态代理主要依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类用于创建一个代理对象,而InvocationHandler接口则定义了处理代理对象调用方法的逻辑。当调用代理对象的...

    JDK动态代理和CGLIB代理

    JDK动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,而InvocationHandler接口定义了处理代理对象的方法调用的逻辑。当通过Proxy创建...

    java动态代理实例(jdk动态代理和cglib)

    3. **生成代理对象**:最后,通过`java.lang.reflect.Proxy.newProxyInstance()`方法,我们可以根据指定的接口和InvocationHandler生成代理对象。 ```java MyInterface target = new MyInterfaceImpl(); // 实现接口...

    proxy.rar java三种代理模式源码

    在Java中,我们可以使用`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。`Proxy`类用于创建代理对象,`InvocationHandler`接口定义了代理对象方法调用的处理逻辑。在"DynamicProxy...

    JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)

    代理机制的核心是`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。以下是一些关键知识点: 1. **Proxy类**:Proxy类是一个工厂类,通过`Proxy.newProxyInstance()`方法可以创建动态代理...

Global site tag (gtag.js) - Google Analytics