黑马程序员_ java高新之动态代理

本文介绍了Java代理的概念,特别是动态代理的实现方式及其在面向切面编程(AOP)中的应用。通过具体示例展示了如何利用JVM动态生成类的字节码来创建代理类,并演示了动态代理的具体使用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1、代理的概念

代理类就是将目标类实现的接口和参数传入从而可以在代理类中对被代理的对象进行操作

2、通过字节码对代理类的使用

1)创建动态类及查看其方法列表信息
<span style="white-space:pre">		</span>//获取Collect接口代理的字节码
		Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		System.out.println(clazzProxy.getName());
		
		//获得代理类的构造器
		Constructor[] constructors = clazzProxy.getConstructors();
		for(Constructor constructor:constructors)
		{
			String name = constructor.getName();
			StringBuilder stringBuilder = new StringBuilder(name);
			stringBuilder.append('(');
			Class[] clazzParameterTypes = constructor.getParameterTypes();
			for(Class clazzType:clazzParameterTypes)
			{
				stringBuilder.append(clazzType.getName()+",");
			}
			if(stringBuilder !=null&& stringBuilder.length()>0)
				stringBuilder.deleteCharAt(stringBuilder.length()-1);
			stringBuilder.append(')');
			
			System.out.println(stringBuilder);
			
		}
		
		//获取代理类的方法
		System.out.println("Method方法开始");
		
		Method	[] methods = clazzProxy.getMethods();
		for(Method method:methods)
		{
			String name = method.getName();
			StringBuilder stringBuilder = new StringBuilder(name);
			stringBuilder.append('(');
			Class[] clazzParameterTypes = method.getParameterTypes();
			for(Class clazzType:clazzParameterTypes)
			{
				stringBuilder.append(clazzType.getName()+",");
			}
			if(stringBuilder !=null&& stringBuilder.length()>0)
				stringBuilder.deleteCharAt(stringBuilder.length()-1);
			stringBuilder.append(')');
			
			System.out.println(stringBuilder);
			
		}
		
		


输出结果:
$Proxy0
$Proxy0(java.lang.reflect.InvocationHandler)
Method方法开始
add(java.lang.Object)
hashCode)
clear)
equals(java.lang.Object)
toString)
contains(java.lang.Object)
isEmpty)
addAll(java.util.Collection)
iterator)
size)
toArray([Ljava.lang.Object;)
toArray)
remove(java.lang.Object)
containsAll(java.util.Collection)
removeAll(java.util.Collection)
retainAll(java.util.Collection)
isProxyClass(java.lang.Class)
getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)
newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)
getInvocationHandler(java.lang.Object)
wait)
wait(long,int)
wait(long)
getClass)
notify)
notifyAll)
    
2) 创建动态类的实例对象及调用其方法
步骤:
a、创建动态类的实例对象。通过反射获得构造方法。 
b、编写一个最简单的InvocationHandler类。 
c、调用构造方法创建动态类的实例对象,并将编写的InvocationHandler类的实例对象传进去。 
d、将创建动态类的实例对象的代理改成匿名内部类的形式编写。
代码如下:
<span style="white-space:pre">		</span>//代理就是把想要代理的类的接口交给代理类,但在代理类内部的InvocationHandler接口的方法还是要传入代理的目标对象,到底<span style="white-space:pre">		</span>//<span style="white-space:pre">	</span>还是对目标对象的操作
		Collection collection2 = (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 {
						
						//把代理对象collect2获得的参数args和操作方法给目标对象target,让目标对象target对操作<span style="white-space:pre">						</span>//方法和参数args进行操作;
						//此步才是代理真正做的事,还是交给被代理的对象做事
						Object retVal =  method.invoke(target, args);
						
						System.out.println(method.getName()+"方法正在运行");
						return retVal;
					}
				});
		
			collection2.add("dsf");
			collection2.add("dsdfsf");
			collection2.add("dsdsf");
			System.out.println(collection2.size());
		
		//Object类只将hashCode ,equals ,toString方法交给InvocationHandler处理
			System.out.println(collection2.getClass().getName());
输出结果:
add方法正在运行
add方法正在运行
add方法正在运行
size方法正在运行
3
$Proxy0


小结:代理就是把想要代理的类的接口交给代理类,但在代理类内部的InvocationHandler接口的方法还是要传入代理的目标对 象,到底还是对目标对象的操作。

3、动态代理

1)aop:交叉业务的编程问题即为面向切面的编程(Aspect oriented program ,简称AOP),AOP的目标就是要使交叉业务模块 化。可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。使用代理技术正好可 以解决这种问题,所以代理是实现AOP功能的核心和关键技术。

2)动态代理技术

JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。JVM生成的动态类必须实现 一个或 多个接口 ,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。 

CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现 接口的类生成动态 代理类,那么可以 使用CGLIB库。 

代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四 个位置加上 系统功能代码:

a、在调用目标方法之前 

b、在调用目标方法之后 

c、在调用目标方法前后 

d、在处理目标方法异常的catch块中




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值