让动态生成的类成为目标类的代理-实现AOP功能的封装与配置

    技术2025-03-12  40

    让动态生成的类成为目标类的代理·分析动态代理的工作原理图

    ·怎样将目标类传递进去? -直接在InvocationHandler实现类中创建目标类的实例对象,可以看运行效果和加入日志代码,但没有实际意义。 -为InvocationHandler实现类注入目标类的实例对象,不能采用匿名内部类的形式了。 -让匿名的InvocationHandler实现类访问外面方法中的目标类实例对象的final类型的引用变量。·将创建代理的过程改为一种更优雅的方式,eclipse重构出一个getProxy方法绑定接收目标同时返回代理对象,让调用者更懒惰,更方便,调用者甚至不用接触任何代理的API。·将系统功能代码模块化,即将切面代码也改为通过参数形式提供,怎样把要执行的系统功能代码以参数形式提供? -把要执行的代码装到一个对象的某个方法里,然后把这个对象作为参数传递,接收者只要调用这个对象的方法,即等于执行类外界 提供的代码! -为bind方法增加Advice参数。以上编程代码:package lqq.heima.day3;

    import java.lang.reflect.Method;

    public interface Advice {  void beforeMethod(Method method); void afterMethod(Method method);

    }package lqq.heima.day3;

    import java.lang.reflect.Method;

    public class MyAdvice implements Advice {

     long beginTime = 0; @Override public void afterMethod(Method method) {  // TODO Auto-generated method stub  System.out.println("张孝祥Java高新技术学习完成了");  long endTime = System.currentTimeMillis();  System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");

     }

     @Override public void beforeMethod(Method method) {  // TODO Auto-generated method stub  System.out.println("张孝祥Java高新技术学习开始了");  beginTime = System.currentTimeMillis();

     }

    }package lqq.heima.day3;

    import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.Collection;

    public class ProxyTest2 {

     /**  * @param args  */ @SuppressWarnings("unchecked") public static void main(String[] args) {  // TODO Auto-generated method stub  final ArrayList target = new ArrayList();  Collection proxy2 = (Collection) getProxy(target,new MyAdvice());  proxy2.add("zxx");  proxy2.add("lhm");  proxy2.add("bxd");  System.out.println(proxy2.size()); }

     private static Object getProxy(final Object target, final Advice advice) {  Object proxy2 = Proxy.newProxyInstance(    target.getClass().getClassLoader(),    /*new Class[]{Collection.class},*/    target.getClass().getInterfaces(),    new InvocationHandler(){     

         @Override     public Object invoke(Object proxy, Method method, Object[] args)       throws Throwable {      // TODO Auto-generated method stub            /*long beginTime = System.currentTimeMillis();      Object  retVal = method.invoke(target, args);      long endTime = System.currentTimeMillis();      System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");      return retVal;*/      //return method.invoke(proxy, args);/*此处如果这样返回调用会形成死循环:我们的类中调用了代理的方法,代理的方法将调用该代理的代理对象、方法名称、和方法的参数传递给类了handler的invoke方法,我们又再handler的invoke方法中调用method的invoke方法将目标回设置成代理对象,造成死循环*/            advice.beforeMethod(method);      Object  retVal = method.invoke(target, args);      advice.afterMethod(method);      return retVal;           }         });  return proxy2; }

    }

    实现AOP功能的封装与配置

    ·工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。·BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:#xxx=java.util.ArrayListxxx=lqq.heima.day3.aopframework.ProxyFactoryBeanxxx.target=java.util.ArrayListxxx.advice=lqq.heima.day3.MyAdvice·ProxyFactoryBean充当封装生成动态代理的工厂,需要为工厂类提供哪些配置参数信息? -目标 -通知·编写客户端应用: -编写实现Advice接口的类和在配置文件中进行配置 -调用BeanFactory获取对象。package lqq.heima.day3;

    import java.lang.reflect.Method;

    public interface Advice {  void beforeMethod(Method method); void afterMethod(Method method);

    }package lqq.heima.day3;

    import java.lang.reflect.Method;

    public class MyAdvice implements Advice {

     long beginTime = 0; @Override public void afterMethod(Method method) {  // TODO Auto-generated method stub  System.out.println("张孝祥Java高新技术学习完成了");  long endTime = System.currentTimeMillis();  System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");

     }

     @Override public void beforeMethod(Method method) {  // TODO Auto-generated method stub  System.out.println("张孝祥Java高新技术学习开始了");  beginTime = System.currentTimeMillis();

     }

    }package lqq.heima.day3.aopframework;

    import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;

    import lqq.heima.day3.Advice;

    public class ProxyFactoryBean { private Advice advice; private Object target;

     public Advice getAdvice() {  return advice; }

     public void setAdvice(Advice advice) {  this.advice = advice; }

     public Object getTarget() {  return target; }

     public void setTarget(Object target) {  this.target = target; }

     public Object getProxy() {  // TODO Auto-generated method stub  Object proxy2 = Proxy.newProxyInstance(    target.getClass().getClassLoader(),    /*new Class[]{Collection.class},*/    target.getClass().getInterfaces(),    new InvocationHandler(){     

         @Override     public Object invoke(Object proxy, Method method, Object[] args)       throws Throwable {      // TODO Auto-generated method stub            /*long beginTime = System.currentTimeMillis();      Object  retVal = method.invoke(target, args);      long endTime = System.currentTimeMillis();      System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");      return retVal;*/      //return method.invoke(proxy, args);/*此处如果这样返回调用会形成死循环:我们的类中调用了代理的方法,代理的方法将调用该代理的代理对象、方法名称、和方法的参数传递给类了handler的invoke方法,我们又再handler的invoke方法中调用method的invoke方法将目标回设置成代理对象,造成死循环*/            advice.beforeMethod(method);      Object  retVal = method.invoke(target, args);      advice.afterMethod(method);      return retVal;           }         });  return proxy2; }

    }package lqq.heima.day3.aopframework;

    import java.io.IOException;import java.io.InputStream;import java.util.Properties;

    import lqq.heima.day3.Advice;

    public class BeanFactory { Properties props = new Properties(); public BeanFactory(InputStream ips){  try {   props.load(ips);  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }   }  @SuppressWarnings("unchecked") public Object getBean(String name){  Object bean =null;  String className = props.getProperty(name);  try {   Class clazz = Class.forName(className);   bean = clazz.newInstance();  } catch (ClassNotFoundException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } catch (InstantiationException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } catch (IllegalAccessException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }  if(bean instanceof ProxyFactoryBean){   ProxyFactoryBean proxyFactoryBean =(ProxyFactoryBean)bean;   Object proxy = null;   try {    Advice advice = (Advice) Class.forName(props.getProperty(name+".advice")).newInstance();    Object target = Class.forName(props.getProperty(name+".target")).newInstance();    proxyFactoryBean.setAdvice(advice);    proxyFactoryBean.setTarget(target);   } catch (InstantiationException e) {    // TODO Auto-generated catch block    e.printStackTrace();   } catch (IllegalAccessException e) {    // TODO Auto-generated catch block    e.printStackTrace();   } catch (ClassNotFoundException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }   proxy = (proxyFactoryBean).getProxy();   return proxy;  }  return bean; }

    }下面是config.properties配置文件的内容:#package lqq.heima.day3.aopframework;xxx=java.util.ArrayList#xxx=lqq.heima.day3.aopframework.ProxyFactoryBeanxxx.target=java.util.ArrayListxxx.advice=lqq.heima.day3.MyAdvicepackage lqq.heima.day3.aopframework;

    import java.io.InputStream;import java.util.Collection;

    public class AopFrameworkTest {

     /**  * @param args  */ @SuppressWarnings("unchecked") public static void main(String[] args) {  // TODO Auto-generated method stub  InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");  Object bean = new BeanFactory(ips).getBean("xxx");  System.out.println(bean.getClass().getName());  Collection col = (Collection) bean;  col.add("123");  System.out.println("col.size() is:"+col.size());  

     }

    }

    最新回复(0)