1.首先區(qū)別一下Spring的動(dòng)態(tài)代理和Spring AOP
2.spring 動(dòng)態(tài)代理ProxyFactory其實(shí)封裝了 CGLIB和JDK,他會(huì)自動(dòng)判斷用那種動(dòng)態(tài)代理,所以開(kāi)發(fā)過(guò)程中可以直接使用Spring的動(dòng)態(tài)代理會(huì)更加方便。
4.這里說(shuō)明一下CGLIB是一個(gè)單獨(dú)的項(xiàng)目,Spring是把CGLIB的源碼copy了一份到Spring中,并非依賴CGLIB的項(xiàng)目(jar 包),從而避免CGLIB升級(jí)影響Spring。
5.
//目標(biāo)對(duì)象或者被代理對(duì)象
UserService target =new UserService();
ProxyFactory proxyFactory =new ProxyFactory();
//設(shè)置目標(biāo)對(duì)象
proxyFactory.setTarget(target);
//這里如果設(shè)置interface就是使用JDK 動(dòng)態(tài)代理。
//proxyFactory.setInterfaces(target.getClass().getInterfaces());
//設(shè)置通知Advice這里有很多Advice - before after around return..
proxyFactory.addAdvice(new MethodBeforeAdvice() {
@Override
? public void before(Method method,Object[] args,Object target)throws Throwable {
//這里和我們寫的JDK CGLIB不一樣,會(huì)在執(zhí)行before后自動(dòng)去執(zhí)行目標(biāo)對(duì)象的方法,不需要通過(guò)metod.invoke(targe,args)
? ? ? System.out.println("before");
}
});
proxyFactory.addAdvice(new AfterReturningAdvice() {
@Override
? public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable {
System.out.println("after returning");
}
});
//around
proxyFactory.addAdvice(new MethodInterceptor() {
@Nullable
@Override
? public Object invoke(@NotNull MethodInvocation invocation)throws Throwable {
System.out.println("around before");
Object proceed = invocation.proceed();//around非常特殊,他的這個(gè)是MethodInterceptor,調(diào)用proceed是讓他繼續(xù)執(zhí)行其他的advice
System.out.println("around after");
return proceed;
}
});
//如果是JDK動(dòng)態(tài)代理這里就會(huì)報(bào)錯(cuò),因?yàn)樯傻拇韺?duì)象是接口對(duì)應(yīng)的子類對(duì)象和UserService沒(méi)關(guān)系
UserService proxy = (UserService)proxyFactory.getProxy();
proxy.test();
4.proxyFactory.addAdvice()可以添加多個(gè)按順序執(zhí)行 - 看上面代碼,最終的執(zhí)行結(jié)果
before - around before - test - around after - after returning
注:before和around before的執(zhí)行順序取決于advice加入的順序
5.類似于CGLib,Spring動(dòng)態(tài)代理也可以指定切方法 Advisor = Adivce + PointCut
所以Advisor可以指定哪個(gè)Adivce應(yīng)用在哪個(gè)方法上
proxyFactory.addAdvisor(new PointcutAdvisor() {
@Override
? public Pointcut getPointcut() {
//指定匹配類型
? ? ? return new StaticMethodMatcherPointcut() {
@Override
? ? ? ? public boolean matches(Method method,Class targetClass) {
return method.getName().equals("test");
}
};
}
@Override
? public Advice getAdvice() {
//指定Advice,這里就不寫了。
? ? ? return null;
}
});