你这头像真恶心,不是为了积分,真不想回答。
代理机制:代理模式是一种常见的设计模式,代理就是控制对目标类(委托类)的访问,代理类和目标类实现了相同的接口,代理是为了给目标对象提供额外的功能或处理,比如异常处理、运行时间、事务管理等等。代理对象并不提供真正的服务,而是调用目标对象的方法提供服务。
动态代理:就是在程序运行时,用反射机制动感创建出来的代理类。对于没有实现接口的类,可以用其子类实现代理。
贴个实现代码:- public class ProxyTest{
- /**1.创建一个实现了Collection接口的动态代理类
- * 2.列出动态类的所有构造方法和参数签名
- * 3.列出动态类的所有方法和参数签名
- * 4.创建动态类的实例对象:用反射获得构造函数
- * 1)编写一个InvocationHandle类
- * 2)调用构造方法传入InvocationHandle实例对象创建动态类实例
- * 3)用匿名内部类的形式创建动态类对象的代理
- * @param args
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws SecurityException
- * @throws NoSuchMethodException
- * @throws InvocationTargetException
- * @throws IllegalArgumentException
- */
- public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
- //1.创建一个实现了Collection接口的动态代理类
- System.out.println("----------get a proxy with collection----------");
- //获取代理类Proxy的字节码文件对象,传入classloader、接口类的字节码文件
- Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
- //System.out.println(ProxyTest.class.getClassLoader());//AppClassLoader
- System.out.println(clazzProxy1.getName());//动态类名:$Proxy0
- //2.列出动态类的所有构造方法和参数签名
- System.out.println("----------proxy constructors list----------");
- Constructor[] constructors=clazzProxy1.getConstructors();
- StringBuilder sb=null;
- for(Constructor constructor:constructors){
- String name=constructor.getName();//$Proxy0
- sb=new StringBuilder(name);
- sb.append('(');
- //遍历构造函数的参数,添加进字符串缓冲区中
- Class[] clazzParas=constructor.getParameterTypes();
- for(Class clazzPara:clazzParas){
- // sb.append(clazzPara.getName()+",");
- sb.append(clazzPara.getName()).append(",");
- }
- if(clazzParas!=null&&clazzParas.length!=0)
- sb.deleteCharAt(sb.length()-1);
- sb.append(')');
- //输出每个构造方法名称和参数列表
- System.out.println(sb);//$Proxy0(java.lang.reflect.InvocationHandler)
- }
- //3.列出动态类的所有方法和参数签名
- System.out.println("----------proxy methods list----------");
- Method[] methods=clazzProxy1.getMethods();
- StringBuilder sb2=null;
- for(Method method:methods){
- String name=method.getName();//$Proxy0
- sb2=new StringBuilder(name);
- sb2.append('(');
- //遍历方法的参数,添加进字符串缓冲区中
- Class[] clazzParas=method.getParameterTypes();
- for(Class clazzPara:clazzParas){
- sb2.append(clazzPara.getName()).append(",");
- }
- if(clazzParas!=null&&clazzParas.length!=0)
- sb2.deleteCharAt(sb2.length()-1);
- sb2.append(')');
- //将每个方法名和参数列表打印出来
- System.out.println(sb2);
- }
- //4.创建动态类的实例对象
- System.out.println("---------creat object of proxy--------");
- //创建方法一:获取代理类的有参构造器new对象
- //Object obj=clazzProxy1.newInstance();不能直接用Class创建对象,因为没有无参构造器
- //创建参数类型实例,传入类的有参构造
- Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
- class myInvocationHandler1 implements InvocationHandler{
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- return null;
- }
- }
- Collection proxy1=(Collection)constructor.newInstance(new myInvocationHandler1());
- System.out.println(proxy1);//null
- /*代理类从Object类继承的方法中,只有hashcode equalse toString3个方法委托给
- InvocationHandler,即会调用目标对象*/
- proxy1.clear();
- //proxy1.size();
- //创建方法二:直接在代理类的有参构造器中传入参数对象
- Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
- return null;
- }
- });
-
- //创建方法三:通过代理类Proxy的newProxyInstance方法直接创建对象
- //newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
- final ArrayList target = new ArrayList();//被代理的对象,实现了Collection的集合
- //传入目标对象、系统功能代码,调用getProxy,生成动态代理对象
- Collection proxy3 =(Collection)getProxy(target,new Advicer());
- //测试,用动态代理类调用目标对象方法
- proxy3.add("xiaotao");
- proxy3.add("panhong");
- proxy3.add("liaojun");
- /*动态代理类内部方法
- $Proxy0{
- InvocationHandler handler;
- public $Proxy0(InvocationHandler handler){
- this.handler=handler;
- }
- add(Object obj){
- return handler.invoke(this, this.getClass().
- getMethod("add",Object.class),obj)
- }
- }
- */
- System.out.println(proxy3.size());
- //clazzProxy1.newInstance();
- }
- //将目标和系统功能代码抽出封装成一个getProxy方法
- private static Object getProxy(final Object target,final Advice advice) {
- Object proxy3=(Object)Proxy.newProxyInstance(
- //定义代理类的类加载器
- //调用newProxyInstance方法时必须与目标类的类加载器和接口一致
- //类A调用了类B,那么B的类加载器就要用A的
- target.getClass().getClassLoader(),
- //代理类要实现的接口列表
- //new Class[]{Collection.class},
- target.getClass().getInterfaces(),
- //传入构造函数调用的InvocationHandle类对象
- new InvocationHandler(){
- /* InvocationHandler代理实例的调用处理程序 实现的接口,
- * 通过实现该接口定义横切逻辑,并反射调用目标类的代码,
- * 动态将横切逻辑和业务逻辑编织在一 起
- */
-
- @Override
- public Object invoke(Object proxy, Method method,
- Object[] args) throws Throwable {
- /*proxy是代理实例,一般不会用到;
- *method是代理实例上的方法,反射调用目标类;
- *args是通过代理类传入 的方法参数,在反射调用时使用
- */
- /*
- //系统功能:测试程序运行时间
- long startTime=System.currentTimeMillis();
- //调用目标方法,将其从return抽出来,加入代理所需的代码
- Object retVal=method.invoke(target, args);
- //系统功能:测试程序运行时间
- long endTime=System.currentTimeMillis();
- //打印测试
- System.out.println(method.getName() +
- " run time of " + (endTime - startTime));
- return retVal;
- */
- //系统功能:测试程序运行时间
- advice.beforeMethod(method);
- //调用目标方法,将其从return抽出来,加入代理所需的代码
- Object retVal=method.invoke(target, args);
- //系统功能:测试程序运行时间
- //打印测试
- advice.afterMethod(method);
- return retVal;
- }
- });
- return proxy3;
- }
- }
- //Advice接口
- package cn.reflect.demo;
- import java.lang.reflect.Method;
- public interface Advice {
- /**
- * 执行的系统功能接口
- * @param args
- */
- abstract void beforeMethod(Method method);
- abstract void afterMethod(Method method);
- }
- //实现Advice接口的Advicer
- package cn.reflect.demo;
- import java.lang.reflect.Method;
- /**
- * @param args
- */
- public class Advicer implements Advice {
- long startTime;
- @Override
- public void beforeMethod(Method method) {
- System.out.print("我们恋爱了!");
- startTime=System.currentTimeMillis();
- }
- @Override
- public void afterMethod(Method method) {
- System.out.print("我们又恋爱了!");
- long endTime=System.currentTimeMillis();
- System.out.println(method.getName() +" run time of " +
- (endTime - startTime));
- }
- public static void main(String[] args) {
- }
- }
复制代码 |