代理proxy

代理:在运行时,创建,实现特定接口的,新类

代理类的方法:

1.实现接口的所有方法

2.Object类的equals,toString,hashCode方法

 

需求:构造一个实现某接口的代理类的对象

思路:

1.反射中获取到类的对象后,可以通过调用newInstance()或者获取到特定Constructor后进行调用,来创建一个此类的实例对象

2.但是,接口不能实例化

3.目标:运行时定义一个新类,条件:有给定接口,方法:使用代理类。场景:void func(Class cInterface)中构造一个实现cInterface接口的对象

 

步骤:

1.创建一个代理类对象Proxy.newProxyInstance():

Objectproxy=Proxy.newProxyInstance(null,new Class[]{Comparable.class},handler);

类似于反射中的newInstance,但代理类的构造实例的方法是静态的,需要提供三个参数:

1).类加载器,null表示使用默认加载器

2).Class对象数组,是需要实现的接口的对象的数组

3).调用处理器

 

2.提供调用处理器

实现InvocationHandler接口,实现Object invoke(Object proxy,Method m,Object[] args)方法

普通类在调用某个方法时是直接调用此方法。而代理类的实例对象调用某个方法时,首先调用的是invoke方法。在invoke方法中使用反射的

m.invoke(target,args);

         proxy是进行调用的代理实例,m是调用方法的对象,args是方法的参数列表

可以在invoke(...)方法中处理代码,在结尾返回时使用return m.invoke(target,args);

 

特点:

1.一个代理类只有一个实例域:传入newProxyInstance/getProxyClass中的调用处理器handler,所有需要处理的数据都必须存储在handler中。

2.代理类只委托Object类的equals,toString,hashCode方法,其他方法由代理类自己实现

3.JVM中生成代理类的类名以$Proxy开头

4.对特定类加载器和接口的组合,只会生成一个代理类。

5.代理类一定是public 和final的。如果代理类实现的所有接口都是public,则代理类不属于特定的包;否则所有非public接口必须属于一个包,代理类也属于这个包。

6.可以使用Proxy的static 方法isProxyClass(Class c)判断一个类是不是代理类





创建一个代理类的类的对象:

ClassproxyClass=Proxy.getProxyClass(null,new Class[]{ [interfaces] });

 

AOP面向方面的编程:使交叉业务模块化,将切面代码移动到原始方法的周围

 

代理类的每个方法会调用目标类的相同方法。并在调用方法时加上新增的功能的代码

 

代理类必须实现至少一个接口(JVM可以通过接口知晓代理类有哪些方法)

 

代理类的各个方法除了调用目标的相应方法并返回目标方法的返回值,还可以在代理方法中调用目标方法的代码的前后添加额外功能

 

示意代码:

Target{

         voidfunc(){//…}

}

Proxy{

         privateTarget t;

         voidfunc(){t.func();}

}



获取代理类的类的对象

Proxy

static Class<?>getProxyClass(ClassLoader loader,Class<?>…interfaces)

类加载器可以选用和接口相同的类加载器,或者填null选择默认

Class c1=Proxy.getProxyClass(Comparable.class.getClassLoader(),Comparable.class);

Classc2=Proxy.getProxyClass(null,Runnable.class);

 

 

 

构造一个代理类的对象,不能直接对Class对象使用newInstance(),因为代理类没有空参数的构造函数

Object proxy=ctor.newInstance(newInvocationHandler(){

         publicvoid invoke(Object proxy,Method method,Object[] args)throws Throwable{

                  

                   returnnull;

         }

})

 

直接创建动态类的实例对象

Proxy.newProxyInstance(loader,Class…interfaces,invocationHandler);

 

注意创建动态类对象时候应当强转成接口的类型,方便使用。否则在调用某方法时可能会因为声明类型没有对应方法而出错

 

代理类只把Object的equals,hashCode,toString方法委托给handler

 

实现InvocationHandler接口需要覆盖

Object invoke(Object proxy,Methodmethod,Object[] args){}

 



import java.lang.reflect.*;
import java.util.*;

interface Advice{
	
	void beforeMethod();
	void afterMethod();	
	void inCatch();
	
	void beforeMethod(Object target,Method method,Object[] args);
	void afterMethod(Object target,Method method,Object[] args);	
	void inCatch(Object target,Method method,Object[] args,Exception e);
	
	void beforeMethod(Method method,Object[] args);
	void afterMethod(Method method,Object[] args);	
	void inCatch(Method method,Object[] args,Exception e); 
}

class AdviceAdapter implements Advice{
	public void beforeMethod() {}
	public void afterMethod() {}
	public void inCatch() {}
	
	public void beforeMethod(Object target, Method method, Object[] args) {}
	public void afterMethod(Object target, Method method, Object[] args) {}
	public void inCatch(Object target, Method method, Object[] args, Exception e) {}
	
	public void beforeMethod(Method method, Object[] args) {}
	public void afterMethod(Method method, Object[] args) {}
	public void inCatch(Method method, Object[] args, Exception e) {}	
}

class ShowMethodInfoAdvice extends AdviceAdapter{
	private long start;	
	public void beforeMethod(Object target, Method method, Object[] args) {
		System.out.print(target.getClass().getName()+"."+method.getName()+"(");		
		if(null!=args){
			for(int i=0;i<args.length;++i){
				System.out.print(args[i]);
				if(i!=args.length-1){
					System.out.print(", ");
				}				
			}
		}		
		System.out.println(")\tstarts at "+(start = System.currentTimeMillis()));
	}
	public void afterMethod(Method method, Object[] args) {
		long end=System.currentTimeMillis();
		System.out.println("This method ends at "+end+", cost "+(end-start));
	}	
}

public class ProxyTest {

	public static void main(String[] args) {
		TreeSet<String> al=new TreeSet<String>();
		Collection c=(Collection)getProxyInstance(al,new ShowMethodInfoAdvice());
		c.add("Rex");
		c.add("milk");
		c.add("metal");
	}
	
	public static <T,U extends Advice> Object getProxyInstance(final T target,final U advice){
		Object newProxy=Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler(){
					public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{						
						advice.beforeMethod(target, method, args);
						Object ret = method.invoke(target, args);
						advice.afterMethod(method, args);
						return ret;						
					}
		});
		
		return newProxy;
	}
	
	/*
	public static Object getProxyInstance(final Object target,final Advice advice){
		Object newProxy=Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler(){
					public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{						
						advice.beforeMethod(target, method, args);
						Object ret = method.invoke(target, args);
						advice.afterMethod(method, args);
						return ret;						
					}
		});
		
		return newProxy;
	}*/
	
	public Object getProxyInstance(final Object target,final Advice advice,final Class ... interfaces){
		
		return null;
	}
	

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值