jdk动态代理

简介: package com.itcast.day3; import java.io.ObjectInputStream.GetField; import java.lang.reflect.Constructor; import java.
package com.itcast.day3;

import java.io.ObjectInputStream.GetField;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
/**
 * 通过反射打印出  代理类的 构造函数、方法以及其参数列表
 * @author liujl
 *
 */
public class ProxyTest {

	public static void main(String[] args) throws Exception{
		Class clazzProxy=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		System.out.println(clazzProxy);

		System.out.println("---------------begin constructors list-----------------");
		Constructor[] constructors=clazzProxy.getConstructors();
		for(Constructor constructor:constructors){
			String name=constructor.getName();
			StringBuilder sb=new StringBuilder(name);
			sb.append("(");
				Class[] clazzParams=constructor.getParameterTypes();
				for(Class clazzParam:clazzParams){
					sb.append(clazzParam.getName());
				}
			if(clazzParams!=null&&clazzParams.length!=0)
				sb.deleteCharAt(sb.length()-1);
			sb.append(")");
			System.out.println(sb);
		}
	
		
		System.out.println("---------------begin methods list-----------------");
		Method[] methods=clazzProxy.getMethods();
		for(Method method:methods){ 
			String name=method.getName();
			StringBuilder sb=new StringBuilder(name);
			sb.append("(");
				Class[] clazzParams=method.getParameterTypes();
				for(Class clazzParam:clazzParams){
					sb.append(clazzParam.getName()).append(",");
				}
			if(clazzParams!=null&&clazzParams.length!=0)
				sb.deleteCharAt(sb.length()-1);
			sb.append(")");
			System.out.println(sb);
		}
		
		
		System.out.println("---------------begin create instance object----------------");
//		clazzProxy.newInstance();//这样不行,这样只会掉那个不带参数的构造方法,而代理对象没有无参构造
		
		
		//第一种方式创建实例
		Constructor constructor=clazzProxy.getConstructor(InvocationHandler.class);
		class MyInvocationHander1 implements InvocationHandler{

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				
				return null;
			}
			
		}
		Collection proxy1=(Collection) constructor.newInstance(new MyInvocationHander1());
		System.out.println(proxy1.toString());
		proxy1.clear();
//		proxy1.size();//java.lang.NullPointerException
		
		
		//第二种方式创建实例
		Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				
				return null;
			}
		});
		
		
		
		
		
		//第三种方式创建代理类的实例,  得到Class  和  创建实例对象  一步到位
		Collection proxy3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), 
				new Class[]{Collection.class},
				new InvocationHandler() {
				ArrayList  target=new ArrayList();//类变量
				@Override
				public Object invoke(Object proxy, Method method, Object[] args)
						throws Throwable {
					StringBuilder sbMethodAndParams=new StringBuilder();
					sbMethodAndParams.append(method.getName()).append("(");
					if(args!=null){
						for(Object obj : args){
							sbMethodAndParams.append(obj.toString()).append(",");
						}
						if(args!=null&&args.length!=0){
							sbMethodAndParams.deleteCharAt(sbMethodAndParams.length()-1);
						}
					}
					sbMethodAndParams.append(")");
					System.out.println(sbMethodAndParams);
					
					long beginTime=System.currentTimeMillis();
					Object retVal=method.invoke(target, args);
					long endTime=System.currentTimeMillis();
					System.out.println(method.getName()+"执行时间 "+(endTime-beginTime)+" 毫秒");
					return retVal;
				}
		});
		
		proxy3.clear();
		
		proxy3.add("ljl");
		proxy3.add("wiseq");
		proxy3.add("traits");
		System.out.println("集合元素的个数="+proxy3.size());
		
		//Proxy也是肯定继承自Object  ,  
		//proxy3.getClass()为啥不调用目标类的getClass()得到ArrayList的字节码? 
		//那是因为Object只有三个方法委托给了InvocationHander,  分别是 toString 、hashCode 、 equals   ,而getClass()方法,生成的代理类有自己的实现
		System.out.println(proxy3.getClass().getName());
	
		
	}

}

 

img_f1bc2e5f583ec27645ba35815aa5d5b7.jpg

把切面的方法以对象的方式封装,把对象传递给代理对象,代理对象执行传入的对象方法 就等于执行了切面的代码

 

 

想上面我们看到的硬编码方式的动态代理在实际的开发中是没有任何意义的,要变的更有用,需要将一些东西抽出去,实现参数化 代理

 

image

 

下一步: 将这个功能封装成一个通用的黑盒子,将目标和系统功能作为参数传入到代理对象中

最终抽取的样子,请看  做一些Spring AOP做过的事

开始做,坚持做,重复做
相关文章
|
4月前
|
缓存 Java 数据库连接
分析JDK动态代理的实现
分析JDK动态代理的实现
39 0
|
7月前
|
Java
jdk动态代理实现原理
jdk动态代理实现原理
36 0
|
29天前
|
Java 程序员 API
浅谈JDK动态代理
浅谈JDK动态代理
31 1
|
2月前
|
Java
关于JDK动态代理
关于JDK动态代理的一些理解
14 0
|
2月前
|
设计模式 Java API
[Java]静态代理、动态代理(基于JDK1.8)
本篇文章主要是对静态代理和动态代理实现思路的简述,以示例为主,少涉及理论。 如果文中阐述不全或不对的,多多交流。
54 1
[Java]静态代理、动态代理(基于JDK1.8)
|
2月前
|
设计模式 安全 Java
深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
317 1
|
3月前
|
Java 数据安全/隐私保护
【面试问题】JDK 动态代理与 CGLIB 区别?
【1月更文挑战第27天】【面试问题】JDK 动态代理与 CGLIB 区别?
|
3月前
|
Java Linux iOS开发
Spring5源码(27)-静态代理模式和JDK、CGLIB动态代理
Spring5源码(27)-静态代理模式和JDK、CGLIB动态代理
23 0
|
3月前
|
Java
JDK动态代理笔记整理
JDK动态代理笔记整理
|
8月前
|
设计模式 Java 数据安全/隐私保护
设计模式之代理模式(jdk和cglib、手撕源码、自创动态代理) 1
设计模式之代理模式(jdk和cglib、手撕源码、自创动态代理)
57 0