动态代理技术

来源:互联网 发布:软件开发w模型 编辑:程序博客网 时间:2024/05/12 16:15

1分析代理类的作用与原理及AOP概念

 当我们已经开发好了一个类,这时我们需要为这个类添加日志,计数,事务管理 那我们什么做???这时我们可以考虑使用代理。代理模式是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用。

代理分为静态代理和动态代理

    1.        代理分类    a)       静态代理:代理类的方法要和接口方式一致!    b)       动态代理,JDK动态代理只能对实现了接口的类进行代理,采用JDK动态代理必须实现InvocationHandler接口,采用Proxy类创建相应的代理类。    c)       动态代理的优缺点:    d)      面向接口编程方便       e)       使用的是Java反射机制 开销比较大。

2. 分析JVM通过反射生成代理类

   JDK 1.5 中代理对象的生成,是通过Proxy 类生成的;   1、创建一个实例对象,先找到有参的构造方法。   2、编写一个最简单的InvotationHander   3、调用动态的方法调用动态的实例对象

代码:三种生成代理对象的方法

packageorg.nagi.proxy;importjava.lang.reflect.Constructor;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Collection;/** *三种方法生成Collection的代理对象 *@author dell * */publicclass TestProxy {   privatestaticCollectionc;   publicstaticvoid main(String[] args)throws Exception {      TestProxy.CreateProxy1();      TestProxy.CreateProxy2();      TestProxy.getProxy(c);   }   /**    *    * 第一种生成代理对象    */   publicstaticvoid CreateProxy1()throws Exception{      //得到代理类      Class classParxy  = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);      //得到其构造方法      Constructor con = classParxy.getConstructor(InvocationHandler.class);      //实现InvocationHander接口      class MyInvocationHanderimplements InvocationHandler{        public Object invoke(Object proxy, Method method,Object[] args)             throws Throwable {          returnnull;        }      }      //生成了Collection的一个代理对象      Collection proxy1 = (Collection)con.newInstance(new MyInvocationHander());   }    /**    *    * 第二种生成代理对象    */   publicstaticvoid CreateProxy2()throws Exception{      //得到代理类      Class classParxy  = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);      //得到其构造方法      Constructor con = classParxy.getConstructor(InvocationHandler.class);      //生成了Collection的一个代理对象      Collection proxy1 = (Collection)con.newInstance(new InvocationHandler(){        @Override        public Object invoke(Object proxy, Method method,Object[] args)             throws Throwable {          returnnull;        }      });   }    /**    *    * 第三种生成代理对象    */   publicstatic Object getProxy(final Object target) {      Object proxy3 = Proxy.newProxyInstance(          //得到目标对象的字节码          target.getClass().getClassLoader(),          //得到目标对象所实现的接口          target.getClass().getInterfaces(),          //实现InvocationHandler接口          new InvocationHandler(){             public Object invoke(Object proxy, Method method,Object[] args)                   throws Throwable {                returnnull;             }          }          );      return proxy3;   }}
    2.创建动态类及查看其方法列表信息    3.创建动态类的实例对象及调用其方法    4.完成InvocationHandler对象的内部功能
public Object invoke(Object proxy, Method method,Object[] args)             throws Throwable {          returnnull;        }

5.分析InvocationHandler对象的运行原理

   我们在调用代理对象的时候,每一次都执行Invocation 里面Invoke方法,而在Invoke 方法需要接收三个数据:哪一个代理对象执行,方法、参数;

5.总结分析动态代理类的设计原理与结构

 思考:我们在调用代理对象的时候都要执行InvocationHander 接口里面的Invoke()方法;如果有一千个类都需要生成代理对象并且他们所需添加功能不一样 那我们什么办?

这时候我们就需要重构以一下我们的所生成的代理方法,使它可以适应为任何类添加的心新功能和生成代理对象; 我们就引出AOP 的思想;在为一个类生成代理对象的时候,我们只徐告诉它目标和需要添加的方法,为了提高可复用性和灵活性,我们把需要生成代理的类写进配置文件里面。

6.编写可生成代理和插入通告的通用方法
通知的方法:

importjava.lang.reflect.Method;/** *通知的借口 *即将插入进来的方法 *如:执行的时间 *   记日记  事务管理 *@author dell * */publicinterface Adrice {   publicvoid beforeClass(Method method);   publicvoid afterClass(Method method);}importjava.lang.reflect.Method;/** *实现通知方法 *@author dell * */publicclass MyAdriceimplements Adrice {   @Override   publicvoid beforeClass(Method method) {      long begain = System.currentTimeMillis();      System.out.println("start....." + begain);   }   @Override   publicvoid afterClass(Method method) {      long after = System.currentTimeMillis();      System.out.println("end....." + after);   }}/**    * 万能代理生成器    * @param target需要代理的对象    * @param adrice需要添加的方法    * @return 代理对象    */   publicstatic Object CreatProxy(final Object target,final Adrice adrice){      Object proxy = Proxy.newProxyInstance(          target.getClass().getClassLoader(),          target.getClass().getInterfaces(),          new InvocationHandler() {             @Override             public Object invoke(Object proxy, Method method,Object[] args)                   throws Throwable {                   adrice.beforeClass(method);                   Object retVal = method.invoke(target, args);                   adrice.afterClass(method);                return retVal;             }          });      return proxy;   }

7.实现类似spring的可配置的AOP框架

首先AOP 存在常用接口:

BeanFactory:负责生产BeanProxyFactoryBean:负责生产Bean 代理对象Adrice: 定义通知的方法接口Config.properties : 配置为哪一个类产生代理对象

代码:

BeanFactory 工厂类packageorg.nagi.Aop;importjava.io.IOException;importjava.io.InputStream;importjava.util.Properties;/** * bean工厂 *@author dell * */publicclass BeanFactory {   Properties prop = new Properties();   public BeanFactory(InputStream is ) {      try {        //从输入流中加载文件        prop.load(is);      } catch (IOException e) {        e.printStackTrace();      }   }   //通过name得到Bean   public Object getBean(String name)throws Exception{    //从配置文件里面加载类    StringclassName = prop.getProperty(name);    //得到文件内存的字节码    Classclazz = Class.forName(className);    //生成一个代理对象    Objectbean = clazz.newInstance();       // 如果是代理工厂的对相的话,就加载代理目标类,和通知adrice      if(beaninstanceof ProxyFactoryBean){        //如果是代理对象,将其转为ProxyFactoryBean        ProxyFactoryBean proxyFactoryBean =(ProxyFactoryBean)bean;        //加载目标代理类        Object target = Class.forName(prop.getProperty(name +".target")).newInstance();         //加载目标的通知        AopAdvice advice = (AopAdvice) Class.forName(prop.getProperty(name +".advice")).newInstance();        //设置通知        proxyFactoryBean.setAdvice(advice);        //设置代理目标类        proxyFactoryBean.setTarget(target);        Object proxy =proxyFactoryBean.CreatProxy();        return proxy;      }      return bean;    }}代理工厂产生类packageorg.nagi.Aop;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 代理工厂 * @author dell * */public classProxyFactoryBean {   private AopAdvice advice;   private Object target;   /**    * 万能代理生成器    *@param target 需要代理的对象    *@param adrice 需要添加的方法    *@return  代理对象    */   public Object CreatProxy(){      Object proxy = Proxy.newProxyInstance(           target.getClass().getClassLoader(),           target.getClass().getInterfaces(),           new InvocationHandler() {              @Override              public Object invoke(Object proxy,Method method, Object[] args)                    throws Throwable {                    advice.beforeClass(method);                    Object retVal = method.invoke(target,args);                    advice.afterClass(method);                 return retVal;              }           });      return proxy;   }   public AopAdvice getAdvice() {      return advice;   }   public void setAdvice(AopAdvice advice) {      this.advice = advice;   }   public Object getTarget() {      return target;   }   public void setTarget(Object target) {      this.target = target;   }}通知接口类packageorg.nagi.Aop;importjava.lang.reflect.Method;/** *通知的借口 *即将插入进来的方法 *如:执行的时间 *   记日记  事务管理 *@author dell * */publicinterface BaseAdvice {   publicvoid beforeClass(Method method);   publicvoid afterClass(Method method);}具体通知实现类 package org.nagi.Aop;importjava.lang.reflect.Method;/** *通知的具体实现类 *@author dell * */publicclass AopAdviceimplements BaseAdvice{   @Override   publicvoid beforeClass(Method method) {      long begain = System.currentTimeMillis();      System.out.println("start....." + begain);   }   @Override   publicvoid afterClass(Method method) {      long after = System.currentTimeMillis();      System.out.println("end....." + after);   }}

配置文件:config.properties

nagi=org.nagi.Aop.ProxyFactoryBeannagi.advice=org.nagi.Aop.AopAdvicenagi.target=java.util.ArrayList

主函数:

packageorg.nagi.Aop;importjava.io.InputStream;/** *测试类 *@author dell * */publicclass TestAop {   publicstaticvoid main(String[] args) {      InputStream is = TestAop.class.getResourceAsStream("config.properties");      BeanFactory factory = new BeanFactory(is);      try {        Object nagi = factory.getBean("nagi");        System.out.println(nagi.getClass().getName());      } catch (Exception e) {        e.printStackTrace();      }   }}

运行结果生成一个代理对象:com.sun.proxy.$Proxy0

0 0
原创粉丝点击