Spring07-aop動態代理
動態代理:
* 作用:不改變原始碼的基礎上,對已有方法增強。(它是AOP思想的實現技術) * 分類: 1.基於介面的動態代理
2.基於子類的動態代理
需要加入的包:
一.基於介面的動態代理
要求:被代理類最少實現一個介面 * 提供者:JDK官方 * 涉及的類:Proxy * 建立代理物件的方法:newProxyInstance(ClassLoader(), Class[], InvocationHandler) * 引數的含義: * ClassLoader:類載入器。和被代理物件使用相同的類載入器。一般都是固定寫法。(類名.getClass().getClassLoader()) * Class[]:位元組碼陣列。被代理類實現的介面。(要求代理物件和被代理物件具有相同的行為)。一般是固定寫法(類名.getClass().getInterfaces()) * InvocationHandler:它是一個介面,就是用於我們提供增強程式碼的。我們一般都是些一個該介面的實現類。實現類可以是匿名內部類。 * 它的含義就是:如何代理。此處的程式碼只能是誰用誰提供。 * 策略模式: * 使用要求:資料已經有了 * 目的明確 * 達到目標的過程就是策略。 * 在dbutils中的ResultSetHandler就是策略模式的具體應用
使用invoke方法:public Object invoke(Object proxy, Method method, Object[] args)
執行被代理物件的任何方法都會經過該方法,該方法有攔截的功能 * 方法的引數 * Object proxy:代理物件的引入。不一定每次都會有。 * Method method:當前執行的方法。 * Object[] args:當前執行方法所需的引數 * 返回值: * 當前執行方法的返回值
package com.lixin.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /* * 模擬一個劇組 */ public class Client { public static void main(String[] args) { final Actor actor=new Actor(); IActor proxyActor= (IActor) Proxy.newProxyInstance(actor.getClass().getClassLoader(), actor.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object rtValue=null; //1.取出執行方法中的引數:給的多少錢 Float money=(Float)args[0]; //2.判斷當前執行的是什麼方法 if("basicAct".equals(method.getName())) { if(money>10000) { //執行方法,開始表演 rtValue=method.invoke(actor, money/2); } } if("dangerAct".equals(method.getName())) { if(money>50000) { //執行方法,開始表演 rtValue=method.invoke(actor, money/2); } } return rtValue; } }); proxyActor.basicAct(20000); proxyActor.dangerAct(60000); } }
二.基於子類的動態代理
要求:被代理類不能是最終類。不能被final修飾 * 提供者:第三方CGLib * 涉及的類:Enhancer * 建立代理物件的方法:create(Class,Callback); * 引數的含義: * Class:被代理物件的位元組碼 * Callback:如何代理。它和InvocationHandler的作用是一樣的。它也是一個介面,我們一般使用該介面的子介面MethodInterceptor * 在使用時我們也是建立介面的匿名內部類。
intercept方法:public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
執行被代理物件的任何方法,都會經過該方法。它是基於介面動態代理和invoke方法的作用是一模一樣的。 * 方法的引數: * 前面三個和invoke方法的引數含義和作用都一樣。 * MethodProxy methodProxy:當前執行方法的代理物件。一般不用
package com.lixin.cglib;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/*
* 模擬一個劇組
*/
public class Client {
public static void main(String[] args) {
final Actor actor=new Actor();
Actor cglibActor=(Actor) Enhancer.create(actor.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object rtValue=null;
//1.取出執行方法中的引數:給的多少錢
Float money=(Float)args[0];
//2.判斷當前執行的是什麼方法
if("basicAct".equals(method.getName())) {
if(money>10000) {
//執行方法,開始表演
rtValue=method.invoke(actor, money/2);
}
}
if("dangerAct".equals(method.getName())) {
if(money>50000) {
//執行方法,開始表演
rtValue=method.invoke(actor, money/2);
}
}
return rtValue;
}
});
cglibActor.basicAct(50000);
cglibActor.dangerAct(100000);
}
}