------- android教育訓練、 java教育訓練、期待與您交流! ----------
代理:要為已存在的多個具有相同接口的目标類的各個方法增加一些系統功能,進而編寫一個與目标類具有
相同接口的代理類,代理類的每個方法調用目标類的相同方法,并在調用方法時加上系統功能的代碼。
AOP:Aspect oriented program(面向方面程式設計)。系統中存在交叉業務,一個交叉業務就是要切入到系統中的一個方面
代理是實作AOP技術的核心。
動态代理技術:
jvm可以在運作時期動态生成類的位元組碼,這種動态生成的類往往被用作代理類,即動态代理類。
jvm生成的動态類必須實作一個或多個接口。是以jvm生成的動态類隻能用作具有相同接口的目标類的代理。
CGLIB庫可以動态生成一個類的子類,一個類的子類也可以用作該類的代理。
是以要為一個沒有實作接口的類生成動态代理類,可以使用CGLIB庫。
代理方法中的系統功能代碼一般在什麼位置:
1.方法調用前,後或者前後都有
2,catch處理塊中
讓jvm建立動态類及其執行個體對象,需要給它提供哪些資訊?
三個方面:
1.生成的類中有哪些方法,通過讓其實作哪些接口的方式進行告知
2.産生的類位元組碼必須有一個關聯的類加載器對象
3.生成的類的方法的代碼是怎樣的,也要由我們提供
建立一個實作Collection接口的動态代理類:
import java.util.*;
import java.lang.reflect.*;
class ProxyTest
{
public static void main(String[] args) throws Exception
{
Collection proxy = 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 Exception
{
Long beginTime = System.currentTimeMillis();
Object retVal = method.invoke(target,args);
Long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" has the running time of "+(endTime-beginTime));
return retVal;
}
}
);
proxy.add("hlx");
proxy.add("qls");
proxy.add("sxfd");
System.out.println(proxy.size());
Iterator it = proxy.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
類似spring的可配置檔案的AOP架構:
需求:
工廠類BeanFactory負責建立目标類或代理類的執行個體對象,并通過配置檔案實作切換。
其getBean方法根據參數字元串傳回一個相應的執行個體對象,
如果參數字元串在配置檔案中對應的類名不是ProxyFactoryBean,則直接傳回該類的執行個體對象,
否則,傳回該類執行個體對象的getProxy方法傳回的對象。
BeanFactory的構造方法接收代表配置檔案的輸入流對象,配置檔案格式如下:
#xxx=java.util.ArrayList
xxx=cn.itcast.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=cn.itcast.MyAdvic
首先 建立BeanFactory類:
package aopframework;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
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();
}
}
public Object getBean(String name){
Object bean = null;
String className = props.getProperty(name);
try {
bean = Class.forName(className).newInstance();//建立bean執行個體對象
} catch (Exception 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);
proxy = proxyFactoryBean.getProxy();//調用getProxy方法,獲得代理類執行個體對象
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return proxy;
}
return bean;
}
}
然後建立ProxyFactoryBean類:
package aopframework;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
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 proxy = Proxy.newProxyInstance(//newProxyInstance接受的參數分别是ClassLoader,interfaces[],Invocationhandler的子類。
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy,Method method,Object[] args){
advice.beforMethod(method);
Object retVal = null;
try {
retVal = method.invoke(proxy, args);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
advice.afterMethod(method);
return retVal;
}
}
);
return proxy;
}
}
建立一個Advice接口
package aopframework;
import java.lang.reflect.Method;
public interface Advice {
void beforMethod(Method method);
void afterMethod(Method method);
}
再建立Advice接口的實作類MyAdvice
package aopframework;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {//系統功能是擷取方法運作時間
long beginTime ;
@Override
public void afterMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("method is ending");
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" using time with " +(endTime-beginTime)+" 毫秒");
}
@Override
public void beforMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("method is beginning");
beginTime = System.currentTimeMillis();
}
}
建立配置檔案config.prpperties
#xxx=java.util.ArrayList
xxx=aopframework.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=aopframework.MyAdvice
最後建立AopFrameworkTest類來測試功能是否實作:
package aopframework;
import java.io.InputStream;
public class AopFrameworkTest {
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());
}
}
總結: 1.這個類似于spring的簡單Aop架構,由BeanFactory和代理類根據配置檔案的配置來擷取一個本類執行個體對象或者代理類對象。 2.BeanFactory類中主要是通過getBean方法來傳回獲得的Bean對象。而在擷取Bean對象後需要判斷是否屬于代理類,如果是,則繼續通過代理類的getProxy方法獲得其代理類對象。 3.JavaBean類必須有一個空參數的構造函數,因為通常bean對象都是通過位元組碼檔案的newInstance方法來獲得的。而這個方法需要類中必須有空參數構造方法。 4.對于架構類,重點是架構的設計思想,了解每個類的存在意義以及類與類之間的層次關系。