JAVA--基礎加強_動態代理
阿新 • • 發佈:2019-02-18
.什麼是動態代理?
一種用於轉發請求,進行特殊處理的機制,“動態”應該指的是“執行期”。
.為什麼使用動態代理?
可以對請求進行任何處理(如事務,日誌等)
.哪些地方需要動態代理?
不允許直接訪問某些類;對訪問要做特殊處理等
JVM可以在執行時期動態生成出類的位元組碼,這種動態生成的類往往被用作代理類,即動態代理類
JVM生成的動態類必須實現一個或多個介面,所以JVM生成的動態類只能用作具有具有相同介面的目標類的代理
CGLIB庫可以動態生成一個類的子類,該子類可以用作該類的代理,如果,沒有實現介面的類生成動態代理類可以使用CGLIB庫
代理類的各個方法中通常除了呼叫目標的相應方法和對外返回目標返回的結果外,還可以再代理方法中如下四個位置增加
系統功能程式碼:
1、在呼叫目標方法之前;
2、在呼叫目標方法之後;
3、在呼叫目標方法前後;
4、在處理目標方法異常的catch塊中;
建立動態類:
建立一個藉口
<span style="font-size:18px;"><strong>import java.lang.reflect.Method;
public interface Advice {
public void beforeMethod(Method method);
public void afterMethod(Method method);
}
</strong></span>
<span style="font-size:18px;"><strong>建立一個實現介面的類 import java.lang.reflect.Method; public class MyAdvice implements Advice{ long beginTime = 0; public void afterMethod(Method method) { System.out.println("學習結束了"); long endTime = System.currentTimeMillis(); System.out.println(method.getName() + " 執行時間" + (endTime - beginTime)); } public void beforeMethod(Method method) { System.out.println("開始學習了"); beginTime = System.currentTimeMillis(); } } </strong></span>
<span style="font-size:18px;"><strong>import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; public class ProxyText { public static void main(String[] args) throws Exception, NoSuchMethodException { // 獲取位元組碼 Class clazzProxy1 = Proxy.getProxyClass(Collection.class .getClassLoader(), Collection.class); System.out.println(clazzProxy1.getName()); System.out.println("----------begin constructors list------------"); /* * $Proxy0() $Proxy0(InvocationHandier,int) */ // 獲取所有構造方法 Constructor[] constructors = clazzProxy1.getConstructors(); for (Constructor constructor : constructors) { String name = constructor.getName(); StringBuilder sBuilder = new StringBuilder(name); sBuilder.append("("); Class[] clazzPrams = constructor.getParameterTypes(); for (Class clazzPram : clazzPrams) { if (clazzPrams != null && clazzPrams.length != 0) { sBuilder.append(clazzPram.getName()).append(","); } } sBuilder.append(")"); System.out.println(sBuilder.toString()); System.out.println("-----------begin methods llist------------"); // 獲得所有的方法 Method[] methods = clazzProxy1.getMethods(); for (Method method : methods) {// 遍歷陣列 String name1 = method.getName();// 獲取方法名 StringBuilder sBuilder1 = new StringBuilder(name1);// 新增容器 sBuilder1.append("("); Class[] clazzPrams1 = method.getParameterTypes();// 返回描述了此 // Method // 物件所表示的方法的形參型別 for (Class clazzPram1 : clazzPrams1) { sBuilder1.append(clazzPram1.getName()); } sBuilder1.append(")"); System.out.println(sBuilder1.toString()); } System.out .println("-----------begin create instance object-----------"); // 建立InvocationHandler的例項物件 Constructor constructor1 = clazzProxy1 .getConstructor(InvocationHandler.class); // 第一種方法 建立MyInvocationHandler1並實現InvocationHandler介面 class MyInvocationHandler1 implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } } Collection proxy1 = (Collection) constructor1 .newInstance(new MyInvocationHandler1()); // 第二種建立方法:用匿名內部類 Collection proxy2 = (Collection) constructor1 .newInstance(new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } }); final ArrayList al = new ArrayList(); Collection proxy3 = (Collection) getProxy(al,new MyAdvice()); // proxy3.add("abc"); // proxy3.add("bcd"); // proxy3.add("cde"); System.out.println(proxy3.size()); } } // //第三種建立的方法:使用newProxyInstance方法 (抽取方法) private static 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 { /* * long beginTime = System.currentTimeMillis(); Object * retVal = method.invoke(target, args); long endTime = * System.currentTimeMillis(); * * System.out.println(method.getName() + " 執行時間" + * (endTime - beginTime)); return retVal; */ advice.beforeMethod(method); Object retVal = method.invoke(target, args); advice.afterMethod(method); return retVal; } }); return proxy3; } } </strong></span>
實現類似spring的可配置的AOP框架程式碼:
<span style="font-size:18px;"><strong>import java.lang.reflect.Method;
public interface Advice {
public void beforeMethod(Method method);
public void afterMethod(Method method);
}
</strong></span>
<span style="font-size:18px;"><strong>
import java.lang.reflect.Method;
public class MyAdvice implements Advice{
long beginTime = 0;
public void afterMethod(Method method) {
System.out.println("學習結束了");
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + " 執行時間"
+ (endTime - beginTime));
}
public void beforeMethod(Method method) {
System.out.println("開始學習了");
beginTime = System.currentTimeMillis();
}
}
</strong></span>
<span style="font-size:18px;"><strong>
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() {
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 {
/*
* long beginTime = System.currentTimeMillis(); Object
* retVal = method.invoke(target, args); long endTime =
* System.currentTimeMillis();
*
* System.out.println(method.getName() + " 執行時間" +
* (endTime - beginTime)); return retVal;
*/
advice.beforeMethod(method);
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
});
return proxy3;
}
}
</strong></span>
<span style="font-size:18px;"><strong>
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
Properties prop = new Properties();
public BeanFactory(InputStream ips){
try {
prop.load(ips);
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getBean(String name){
String className = prop.getProperty(name);
Object bean = null;
try {
Class clazz = Class.forName(className);
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 advice = (Advice) Class.forName(prop.getProperty(name + ".advice")).newInstance();
Object target = Class.forName(prop.getProperty(name + ".target")).newInstance();
proxyFactoryBean.setAdvice(advice);
proxyFactoryBean.setTarget(target);
proxy = proxyFactoryBean.getProxy();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return proxy;
}
return bean;
}
}
</strong></span>
<span style="font-size:18px;"><strong>
config.properties 檔案
#xxx=java.util.ArrayList
xxx=aopFactoryWork.ProxyFactoryBean
xxx.target=aopFactoryWork.MyAdvice
xxx.advice=java.util.ArrayList</strong></span>
<span style="font-size:18px;"><strong>//測試類</strong></span>
<span style="font-size:18px;"><strong>import java.io.InputStream;
public class AopFrameworkTexst {
public static void main(String[] args) {
InputStream ips = AopFrameworkTexst.class.getResourceAsStream("config.properties");
Object bean = new BeanFactory(ips).getBean("xxx");
System.out.println(bean.getClass().getName());
}
}</strong></span>