客戶端調用代理,代理的構造方法接收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");//調用prosy3的InvocationHandler對象的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