java中的代理是什麼呢?
比如說我們用到一個類A ,我們往常的方法就是直接使用這個類A ,這樣在大型的軟體開發中有很大的局限性、 。 我們對于使用的類A的修改隻能通過對源檔案寫死的修改,
代理就很好的突破了這個瓶頸。
在代理中我們可以定義一個類B,這個類B有個特點 就是和類A有着實作同樣的接口 ,我們在類B中間接的調用了 類A, 我們也可以向這個代理的類插入一些通告消息類 。
着在開發架構中經常用到 。
在JAVA中用于動态生成代理類的類 就是 java.lang.reflect.Proxy 這個類 具體的使用 可以去 看看有關于JDK的文檔 。
在AOP的程式設計中,InvocationHandler 這個類是作為代理類對于target類的間接調用者 ,所有的被代理類都是通過 這個InvocationHandler這個類來進行調用的 。
我們在對這些步驟進行操作的時候 隻需要把實作過程封裝起來 把 需要代理的類 作為Object傳遞進去 那麼就可以實作 代理的通用化 ,于是一個小java架構就産生了 。
在使用的過程用 涉及到匿名内部類 ,這裡提到 在匿名内部類中調用外部的對象 需要 吧外面的對象 聲明為 final 。。。。 這是java的文法 為了是保證資料的安全性。。
StirngBuffer是一個線程安全的類,繼承了String在多線程中用到 。
如果隻涉及到 單線程那麼 就用 StringBuilder這個類 效率會提高很多。。
關于代理的結構圖如下:
下面我寫一個例子來實作動态代理 :
package me.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.lang.reflect.TypeVariable;
public class MyProxy
{
public static void main(String []args) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
{
Class clazzProxy=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class) ; //利用Proxy類産生一份代理類的位元組碼
//Create a Dynamic Class by using Proxy
Constructor constructors[]=clazzProxy.getConstructors() ; //獲得代理類的構造方法數組 反射原理
Method []methods=clazzProxy.getMethods() ; //獲得代理類的方法
System.out.println("Constructor List:");
for(Constructor con:constructors)
{
String cons=con.getName() ;
StringBuilder conBuilder=new StringBuilder(cons) ;
Class []types = con.getParameterTypes() ;
conBuilder.append('(') ;
if(types.length!=0&&types!=null)
{
for(Class type:types)
{
conBuilder.append(type.getName()) ;
conBuilder.append(',') ;
}
conBuilder.deleteCharAt(conBuilder.lastIndexOf(",")) ;
}
conBuilder.append(')') ;
System.out.println(conBuilder);
}
System.out.println("Methoid list:");
for(Method med:methods)
{
String cons=med.getName() ;
Class []types = med.getParameterTypes() ;
/////////////////////////////////////////////////////////////這裡是代理類的實作部分
class MyInvocationHandler implements InvocationHandler
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
Collection cn1=(Collection)constructors[0].newInstance((new MyInvocationHandler())) ; //生成一個代理類的對象 這個對象實作了 Collection接口
System.out.println(cn1.toString());
/*************************************************************************************/
Collection cn2=(Collection)constructors[0].newInstance(new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
}) ;
/***************************************************************************************/
final ArrayList list=new ArrayList() ;
Advice adv=new MyAdvice() ; //通告類 對象
Collection cn3 = getProxy(list, adv);
cn3.add("xiaowei") ; //會調用 對于代理類的操作會調用InvocationHandler的invoke方法 進行調用目标類 ,調用方法如同反射 機制
cn3.add("man") ;
cn3.add("軟體技術") ;
System.out.println("包含"+cn3.size()+"個元素!") ;
for(Object obj:cn3)
{
System.out.println(obj.toString());
}
private static Collection getProxy(final Object list ,final Advice advice) {
Collection cn3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler()
/* @Override
public Object invoke(Object proxy, Method method, Object[] args) //代理類在執行每一個被代理類的方法的時候 就會調用這個invoke方法 并且傳遞Method對象 我們就可以動态的調用目的類的方法
throws Throwable {
// ArrayList list=new ArrayList() ; //必須作為一個成員來實作 否則 每次進行插入操縱那麼調用的都是一個新的對象
Long beginTime=System.currentTimeMillis() ;
Object returnVal= method.invoke(list, args); //Invoke the Method
Long endTime=System.currentTimeMillis() ;
System.out.println("Runtime="+(endTime-beginTime));
return returnVal;
}*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// ArrayList list=new ArrayList() ; //必須作為一個成員來實作 否則 每次進行插入操縱那麼調用的都是一個新的對象
advice.beginRun(method) ; //内部類調用外部的對象的時候 需要使用 final聲明
Object returnVal= method.invoke(list, args); //Invoke the Method 執行代理傳遞過來的執行方法
advice.afterRun(method) ;
return returnVal;
}
);
return cn3;
}
//////////////////////////////////////////////////////////////////////////通告接口 和實作類
package me.test;
public interface Advice
{
public void beginRun(Method method) ;
public void afterRun(Method method) ;
public class MyAdvice implements Advice{
long beginTime ;
@Override
public void beginRun(Method method ) {
beginTime=System.currentTimeMillis() ;
public void afterRun(Method method) {
long endTime=System.currentTimeMillis() ;
System.out.println(method.getName()+"運作了"+(endTime-beginTime)+"ms!");
}