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做过的事

开始做,坚持做,重复做
相关文章
|
8月前
|
Java Spring
JDK动态代理和CGLIB动态代理的区别
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理: ● JDK动态代理只提供接口的代理,不支持类的代理Proxy.newProxyInstance(类加载器, 代理对象实现的所有接口, 代理执行器) ● CGLIB是通过继承的方式做的动态代理 , 如果某个类被标记为final,那么它是无法使用 CGLIB做动态代理的。Enhancer.create(父类的字节码对象, 代理执行器)
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
8月前
|
监控 Java API
JDK动态代理和CGLIB动态代理
Java动态代理允许在运行时创建代理对象,增强或拦截目标类方法的执行。主要通过两种方式实现:JDK动态代理和CGLIB动态代理。JDK动态代理基于接口,利用`java.lang.reflect.Proxy`类和`InvocationHandler`接口;CGLIB则通过字节码技术生成目标类的子类作为代理,适用于未实现接口的类。两者均用于在方法执行前后添加额外逻辑,如日志记录、权限控制等,广泛应用于AOP框架中。
286 2
|
9月前
|
监控 Java API
JDK动态代理和CGLIB动态代理
Java动态代理允许在运行时创建代理对象,增强或拦截目标类的方法调用,无需修改原代码。它有两种主要实现方式:JDK动态代理和CGLIB动态代理。 - **JDK动态代理**:通过`java.lang.reflect.Proxy`类和`InvocationHandler`接口实现,适用于实现了接口的类。它在方法调用前后插入额外逻辑,如日志记录、权限控制等。 - **CGLIB动态代理**:基于字节码技术,为未实现接口的类生成子类作为代理,重写父类方法以添加增强逻辑。适用于没有接口的类,但要求目标类不能是`final`类或方法。
127 1
|
9月前
|
Java API 数据安全/隐私保护
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
272 0
探索Java动态代理的奥秘:JDK vs CGLIB
|
12月前
|
安全 Java 开发者
AOP中的JDK动态代理与CGLIB动态代理:深度解析与实战模拟
【11月更文挑战第21天】面向切面编程(AOP,Aspect-Oriented Programming)是一种编程范式,它通过将横切关注点(cross-cutting concerns)与业务逻辑分离,以提高代码的可维护性和可重用性。在Java开发中,AOP的实现离不开动态代理技术,其中JDK动态代理和CGLIB动态代理是两种常用的方式。本文将从背景、历史、功能点、业务场景、底层逻辑等多个维度,深度解析这两种代理方式的区别,并通过Java示例进行模拟和比较。
819 5
|
Java
【编程进阶知识】静态代理、JDK动态代理及Cglib动态代理各自存在的缺点及代码示例
本文介绍了三种Java代理模式:静态代理、JDK动态代理和Cglib动态代理。静态代理针对特定接口或对象,需手动编码实现;JDK动态代理通过反射机制实现,适用于所有接口;Cglib动态代理则基于字节码技术,无需接口支持,但需引入外部库。每种方法各有优缺点,选择时应根据具体需求考虑。
152 1
|
Java API 开发者
Jdk动态代理为啥不能代理Class?
该文章主要介绍了JDK动态代理的原理以及为何JDK动态代理不能代理Class。
Jdk动态代理为啥不能代理Class?
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
1125 0
|
设计模式 Java C++
揭秘!JDK动态代理VS CGLIB:一场关于Java代理界的‘宫心计’,你站哪队?
【8月更文挑战第24天】Java 动态代理是一种设计模式,允许在不改动原类的基础上通过代理类扩展功能。主要实现方式包括 JDK 动态代理和 CGLIB。前者基于接口,利用反射机制在运行时创建代理类;后者采用继承方式并通过字节码技术生成子类实现类的代理。两者在实现机制、性能及适用场景上有明显差异。JDK 动态代理适用于有接口的场景,而 CGLIB 更适合代理未实现接口的类,尽管性能更优但存在一些限制。开发者可根据需求选择合适的代理方式。
546 0