动态代理技术

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:负责生产Bean
ProxyFactoryBean:负责生产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.ProxyFactoryBean
nagi.advice=org.nagi.Aop.AopAdvice
nagi.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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值