1、Spring Aop中使用到了動態代理技術,對於jdk動態代理,要求必須代理接口,底層是java的反射機制,對於類,使用cglib字節碼增強來動態代理
2、設計模式中簡單的代理模式實現
3、jdk動態代理的實現方法
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//實現了InvocationHandler接口並實現了它的invoke方法
public class ProxyTest implements InvocationHandler{
//目標代理對象
private Object target;
public ProxyTest(){
}
//帶參的構造函數,用於傳遞目標代理對象
public ProxyTest(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("執行方法前");
//代理對象執行對應的方法 在前面後後面都加上了代碼,這是Aop的一種實現方式,面向切面編程
method.invoke(target, args);
System.out.println("執行方法後");
return target;
}
public static void main(String[] args) {
//創建需要被代理的對象
Sky sky1 = new ProxyTest().new SkyImpl();
//創建代理對象
ProxyTest proxyTest = new ProxyTest(sky1);
//生成代理對象
Sky sky = (Sky)Proxy.newProxyInstance(SkyImpl.class.getClassLoader(), SkyImpl.class.getInterfaces(),proxyTest );
//執行方法
sky.rain();
}
interface Sky{
void rain();
}
class SkyImpl implements Sky{
public void rain() {
System.out.println("天下雨了");
}
}
}
4、運行結果
5、反編譯過後,實際上是代理類繼承了Proxy類並且實現了對應代理的接口,由於java只能支持單繼承,所以jdk代理只適用於代理接口,例如 $ProxyClass extends Proxy implements Sky
6、cglib動態代理案例,需要在maven中添加cglib的依賴包
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
//設置需要代理的類
enhancer.setSuperclass(HelloServiceImpl.class);
//設置回調方法
enhancer.setCallback(new HelloMethodInterceptor());
//創建代理對象
HelloServiceImpl helloServiceImpl = (HelloServiceImpl)enhancer.create();
//調用代理對象的方法
helloServiceImpl.sayHello();
}
}
//被代理的類
class HelloServiceImpl{
public void sayHello(){
System.out.println("Hello,World!");
}
}
class HelloMethodInterceptor implements MethodInterceptor{
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("方法調用前");
//執行代理對象的方法 在前面後面加通知都可以
methodProxy.invokeSuper(obj, args);
System.out.println("方法調用後");
return obj;
}
}
7、執行的結果
8、cglib是一種字節碼增強的動態代理技術,它代理的是類,而具體的實現是代理類繼承了需要被代理的類,並增強了它的方法 $ProxyClass extends HelloServiceImpl 注意:cglib不能代理final修飾的類,也不能代理final修飾的方法,因爲不能重寫