黑馬程序員——Java動態類,代理

---------------------- android培訓java培訓、期待與您交流! ----------------------

客戶端調用代理,代理的構造方法接收Handler對象

客戶端調用代理的各個方法,代理將方法把調用請求轉發給剛纔傳進來的Handler對象

Handler對象又把請求發給目標的相應的方法

注意兩點:

1.       代理接收Handler對象

2.       Handler對象的invoke() ,可以添加其他方法,通過method實現與target的溝通

 

 

分析JVM動態生成類

創建實現了Collection接口的動態類和查看其名稱,分析Proxy.getProxy方法的各個參數,

編碼列出動態類中所有的構造方法和參數簽名

編碼列出動態類中的所有方法和參數簽名

創建動態類的實例對象

用反射獲得構造方法

編寫一個最簡單的InvocationHandler

調用構造方法創建動態類的實例對象,並將編寫的InvocationHandler類的實例對象進去

但因創建的對象和調用對象的沒有返回值的方法和getClass方法,演示調用其他有返回值報告了異常,

將創建動態類的實例對象的代理改成匿名內部類的形式編寫,

 public static void main(String[] args) throws Exception {
  // TODO Auto-generated method stub
  //創建實現Cllection接口的動態類
  //兩個參數    類加載器Collection.class.getClassLoader()  Collection.class)字節碼
  Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
  System.out.println(clazzProxy1.getName());
  System.out.println("-----------------begin constructors list--------------");
  //得到構造函數
  Constructor[] constructors = clazzProxy1.getConstructors();
  for(Constructor constructor:constructors){
   String name = constructor.getName();
   StringBuilder sb = new StringBuilder(name);
   sb.append('(');
   //方法的參數裏表
   Class[] clazzParams = constructor.getParameterTypes();
   for(Class clazzParam: clazzParams){
    sb.append(clazzParam.getName()).append(',');
    if(clazzParams!=null&& clazzParams.length!=0)
     //去掉最後一個','
    sb.deleteCharAt(sb.length()-1);
    
   }
   sb.append(')');
   System.out.println(sb.toString());
  }

 

打印結果-----------------begin constructors list--------------
$Proxy0(java.lang.reflect.InvocationHandler)

構造方法只有一個有參數的構造方法
  System.out.println("-----------------begin methods list--------------");
  //打印方法
  Method[] methods = clazzProxy1.getMethods();
  for(Method method:methods){
   String name = method.getName();
   StringBuilder sb = new StringBuilder(name);
   sb.append('(');
   Class[] clazzParams = method.getParameterTypes();
   for(Class clazzParam: clazzParams){
    sb.append(clazzParam.getName()).append(',');
    if(clazzParams!=null&& clazzParams.length!=0)
    sb.deleteCharAt(sb.length()-1);
    
   }
   sb.append(')');
   System.out.println(sb.toString());
  }

三種方法創建實例對象

/利用構造函數創建一個實例對象第一種方法法

       Collection proxy1 =(Collection) constructor.newInstance(new MyinvocationHandler());

       System.out.println(proxy1);//打印結果爲null有疑問到底toString()放回爲爲null還是空對象,肯定是

       System.out.println(proxy1.toString());//顯示調用toString來驗證長度爲零。

       proxy1.clear();//返回值類型爲void

       //proxy1.size();//會報空指針異常 因爲調用代理類中的invoke(),返回值是null所以會報空指針異常

      

       //使用匿名內部類創建對象第二種方法

       Collection proxy2 =(Collection) constructor.newInstance(new InvocationHandler(){

 

          @Override

          public Object invoke(Object proxy, Method method, Object[] args)

                 throws Throwable {

             //TODO Auto-generated method stub

             returnnull;

          }

          

       });

       第三種方法

    Collection proxy3 =(Collection) Proxy.newProxyInstance(

             Collection.class.getClassLoader(),

            new Class [] {Collection.class},

            new InvocationHandler(){

 

               ArrayList target = new ArrayList();   

                public Object invoke(Object proxy, Method method, Object[] args)

                       throws Throwable {

                   //怎麼理解target  暫時寫到了內部的目標,實際應該抽取出來的

                   //ArrayList target = new ArrayList();

                   long beginTime = System.currentTimeMillis();

                   Object retVal = method.invoke(target, args);

                   long endTime = System.currentTimeMillis();

                   System.out.println(method.getName()+" running time " +(endTime-beginTime));

                   return retVal;

                }

               

            }

            );

 

將目標和方法和代理中新增加的方法抽取出來

    //把目標和方法抽出來

       finalArrayList target =newArrayList();//內部類訪問局部成員只能使用final修飾的

       Collection proxy3 = (Collection)getProxy(target,new MyAdvice());//抽取方法

       proxy3.add("dd");//調用prosy3InvocationHandler對象的invoke()

       proxy3.add("ma");

       proxy3.add("zzp");

       System.out.println(proxy3.size());

 

    }

 

    privatestatic Object getProxy(final Object target,final Advice advice) {

       Object proxy3 = Proxy.newProxyInstance(

             target.getClass().getClassLoader(),

            //new Class [] {Collection.class},

             target.getClass().getInterfaces(),

            new InvocationHandler(){

 

              

                public Object invoke(Object proxy, Method method, Object[] args)

                       throws Throwable {

                       //ArrayList target = new ArrayList();

                /*  long beginTime = System.currentTimeMillis();

                   Object retVal = method.invoke(target, args);

                   long endTime = System.currentTimeMillis();

                   System.out.println(method.getName()+" running time " +(endTime-beginTime));

                   return retVal;*/

                  

                  

                   advice.beforeMethod(method);

                   Object retVal = method.invoke(target, args);

                   advice.afterMethod(method);

               

                   return retVal;

                }

               

            }

            );

       return proxy3;

    }

 

Advice.java

import java.lang.reflect.Method;

public interface Advice {

 void beforeMethod(Method method);
 void afterMethod(Method method);
}

 

寫一個Advice的實現類

import java.lang.reflect.Method;

public class MyAdvice implements Advice {
 long beginTime=0;
 @Override
 public void beforeMethod(Method method) {
  System.out.println("begin study! ");
  beginTime = System.currentTimeMillis();

 }

 @Override
 public void afterMethod(Method method) {
  System.out.println("end study!");
  long endTime = System.currentTimeMillis();
  System.out.println(method.getName()+" running time " +(endTime-beginTime));

 }

}

 

  final ArrayList target = new ArrayList(); //內部類訪問局部成員只能使用final修飾的
  Collection proxy3 = (Collection)getProxy(target,new MyAdvice()); //抽取方法
  proxy3.add("dd");//調用prosy3的InvocationHandler對象的invoke()
  proxy3.add("ma");
  proxy3.add("zzp");
  System.out.println(proxy3.size());

運行查看效果:

egin study!
end study!
add running time 0
begin study!
end study!
add running time 0
begin study!
end study!
add running time 0
begin study!
end study!
size running time 0
3

 

AOP功能的創建與配置

BeanFactory.getBean(“xxx”)  創建一個實例對象

如果是

xxx=java.util.ArrayList

直接創建bean

如果是

xxx=cn.itcast.ProxyFactoryBean

需要創建代理,在創建對象

config.properties

xxx=java.util.ArrayList

xxx=cn.itcast.ProxyFactoryBean

xxx.adviec=

xxx.target=

 首先定義BeanFactory

public class BeanFactory {
 Properties props = new Properties();

 public BeanFactory(InputStream ips){
  try {
   props.load(ips);
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 public Object getBean(String name){
        String classname =  props.getProperty(name);
        Object bean = null;
        try {
   Class clazz = Class.forName(classname);
   //Javabean必須有一個不帶參數的構造方法
   bean = clazz.newInstance();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
        //如果是特殊的類就創建代理
        if(bean instanceof ProxyFactoryBean){
         Object proxy=null;
         ProxyFactoryBean  proxyFactoryBean =(ProxyFactoryBean) bean;
         try {
          //得到代理的advice和target
    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);
   //生成代理
    proxy =(proxyFactoryBean).getProxy();
  }  catch (Exception e) {
   e.printStackTrace();
  }
         return proxy; 
        }
  return bean;
 }
}

 

定義ProxyFactoryBean

public class ProxyFactoryBean {
 private Advice advice;
 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;
 }

 private Object target;

 public Object getProxy() {
   Object proxy = Proxy.newProxyInstance(
     target.getClass().getClassLoader(),
        //new Class [] {Collection.class},
     target.getClass().getInterfaces(),
        new InvocationHandler(){
 public Object invoke(Object proxy, Method method, Object[] args)
           throws Throwable { 
          advice.beforeMethod(method);
          Object retVal = method.invoke(target, args);
          advice.afterMethod(method);
         
          return retVal;
         }
         
        }
        );
   return proxy;
  }

 }

配置文件

#xxx=java.util.ArrayList
xxx=cn.itcast.day3.aopframework.ProxyFactoryBean
xxx.advice=cn.itcast.day3.MyAdvice
xxx.target=java.util.ArrayList

測試類AopFrameWorkTest

public class AopFrameWorkTest {

 /**
  * @param args
  */
 public static void main(String[] args) throws Exception{
  // 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) bean).clear();
 }

}

 

運行結果

$Proxy0
begin study!
end study!
clear running time 31

 

 

---------------------- android培訓java培訓、期待與您交流! ----------------------詳細請查看:http://edu.csdn.net/heima
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章