源碼地址:
https://github.com/yixuaz/myspring
如看在開始前,你還不知道動態(tài)代理在JAVA里的2種實現(xiàn)方式,不知道BEAN POST PROCESSOR的作用。
請先看SPRING AOP 準備工作
我們開始吧。
首先同樣我們要定一個目標。
AOP 的XML 應該是什么樣的呢?
Step1. 在IOC 的XML 基礎上加上這3行, 構建代理接口,實現(xiàn)2種代理
<bean id="autoProxyCreator" class="com.myspring.aop.AspectJAwareAdvisorAutoProxyCreator"></bean>
<bean id="timeInterceptor" class="com.myspring.aop.TimerInterceptor"></bean>
<bean id="aspectjAspect" class="com.myspring.aop.AspectJExpressionPointcutAdvisor">
<property name="advice" ref="timeInterceptor"></property>
<property name="expression" value="execution(* com.myspring.*.*(..))"></property>
</bean>
把該有的類創(chuàng)建出來。
現(xiàn)在XML 如下

這里的TIME INTERCEPTOR, 就是一個代理方法,也稱增強方法,它的作用就是讓被切到的方法,都做一個計時的增強。
為了方面我們需要引入2個AOP提供的接口。當然自己實現(xiàn)也是可以的。因為是接口。所以我們?yōu)榱送祽兄苯右?br>
POM.XML 加上
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
這個類寫出來
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class TimerInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
long time = System.nanoTime();
System.out.println("Invocation of Method " + invocation.getMethod().getName() + " start!");
Object proceed = invocation.proceed();
System.out.println("Invocation of Method " + invocation.getMethod().getName() + " end! takes " + (System.nanoTime() - time)
+ " nanoseconds.");
return proceed;
}
}
因為AOP需要代理所以我們定一個代理接口,因為代理有2種實現(xiàn),一種是JDK,一種是CGLIB。所以我們需要一個接口來屏幕底層實現(xiàn)。因為用戶不需要關心底層SPRING用了什么實現(xiàn)。
public interface AopProxy {
Object getProxy();
}
下面在實現(xiàn)JDK的代理類前我們要思考,因為JDK的實現(xiàn)里,就是INVOKE里面,一個反射調用,在INVOKE方法位置做增強

我們寫AOP為了通用一點,我們應該用methodInterceptor這個接口表示增強方法。然后調用這個INVOKE方法。
那這個方法又是傳入一個METHOD INVOCATION,里面封裝了,這個增強方法要的一切參數(shù),不如我們先把這個實現(xiàn)類給寫掉。
public class ReflectiveMethodInvocation implements MethodInvocation {
private Object target;
private Method method;
private Object[] args;
public ReflectiveMethodInvocation(Object target, Method method, Object[] args) {
this.target = target;
this.method = method;
this.args = args;
}
@Override
public Method getMethod() {
return method;
}
@Override
public Object[] getArguments() {
return args;
}
@Override
public Object proceed() throws Throwable {
return method.invoke(target, args);
}
@Override
public Object getThis() {
return target;
}
@Override
public AccessibleObject getStaticPart() {
return method;
}
}
解決了INVOCATION的問題,下面看還缺什么
在取得代理對象的時候,我們需要一個TAR 的CLASS 還有 INTERFACES。

所以增強方法和要代理的元數(shù)據(jù),我們可以封裝在一起,作為一個類,傳入JDK動態(tài)代理PROXY里
這個類就叫AdvisedSupport
public class TargetSource {
private Class targetClass;
private Class[] interfaces;
private Object target;
public TargetSource(Object target, Class<?> targetClass,Class<?>[] interfaces) {
this.target = target;
this.targetClass = targetClass;
this.interfaces = interfaces;
}
public Class getTargetClass() {
return targetClass;
}
public Object getTarget() {
return target;
}
public Class[] getInterfaces() {
return interfaces;
}
}
public class AdvisedSupport {
MethodInterceptor methodInterceptor;
TargetSource targetSource;
public MethodInterceptor getMethodInterceptor() {
return methodInterceptor;
}
public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
public TargetSource getTargetSource() {
return targetSource;
}
public void setTargetSource(TargetSource targetSource) {
this.targetSource = targetSource;
}
}
有了這個類之后,我們就可以把JDK PROXY寫掉了。
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
AdvisedSupport advisedSupport;
public JdkDynamicAopProxy(AdvisedSupport advisedSupport) {
this.advisedSupport = advisedSupport;
}
@Override
public Object getProxy() {
return Proxy.newProxyInstance(getClass().getClassLoader(),
advisedSupport.getTargetSource().getInterfaces()}, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInterceptor methodInterceptor = advisedSupport.getMethodInterceptor();
return methodInterceptor.invoke(new ReflectiveMethodInvocation(advisedSupport.getTargetSource().getTarget(), method, args));
}
}
來做個簡單的測試
為了測試JDK,必須要有INTERFACE,我們就為HELLOWORLD,建一個接口
public interface HelloWorldService {
void helloWorld();
}
測試
@Test
public void testInterceptor() throws Exception {
// --------- helloWorldService without AOP
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService");
helloWorldService.helloWorld();
// --------- helloWorldService with AOP
// 1. 設置被代理對象(Joinpoint)
AdvisedSupport advisedSupport = new AdvisedSupport();
TargetSource targetSource = new TargetSource(helloWorldService, helloWorldService.getClass(), helloWorldService.getClass().getInterfaces());
advisedSupport.setTargetSource(targetSource);
// 2. 設置攔截器(Advice)
TimerInterceptor timerInterceptor = new TimerInterceptor();
advisedSupport.setMethodInterceptor(timerInterceptor);
// 3. 創(chuàng)建代理(Proxy)
JdkDynamicAopProxy jdkDynamicAopProxy = new JdkDynamicAopProxy(advisedSupport);
HelloWorldService helloWorldServiceProxy = (HelloWorldService) jdkDynamicAopProxy.getProxy();
// 4. 基于AOP的調用
helloWorldServiceProxy.helloWorld();
}
測試成功:
output:Hello World!
Invocation of Method helloWorld start!
output:Hello World!
Invocation of Method helloWorld end! takes 89181 nanoseconds.
當前項目結構:

Step2 上述代碼解決了怎么代理增強的問題,我們下面要解決怎么切的問題
還記得XML里* com.myspring..(..) 嗎?
這個就是表示,切面的范圍。
對于“在哪切”這一問題的定義,我們又叫做“Pointcut”。Spring中關于Pointcut包含兩個角色:ClassFilter和MethodMatcher,分別是對類和方法做匹配。Pointcut有很多種定義方法,例如類名匹配、正則匹配等,但是應用比較廣泛的應該是和AspectJ表達式的方式。
根據(jù)上述定義,我們先寫一個POINTCUT 接口
public interface ClassFilter {
boolean matches(Class targetClass);
}
public interface MethodMatcher {
boolean matches(Method method, Class targetClass);
}
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
我們有了切面的接口,下面是怎么切的定義,這就是ADVISE()
在AOP里有環(huán)繞通知,前置通知,后置通知,異常通知,返回通知等。
定義一個獲取通知類型的接口
import org.aopalliance.aop.Advice;//這里偷懶
public interface Advisor {
Advice getAdvice();
}
再來一個接口去獲取切面和通知的的
public interface PointcutAdvisor extends Advisor{
Pointcut getPointcut();
}
接口全部定義好啦!
Step3 實現(xiàn)切面
首先把三個接口都實現(xiàn)下。
隨后對于這個類來說,我們肯定會拿到一個ASPECJ表達式。所以這個表達式,要注入進來的。加一個expression 變量。
隨后,我們要解析這個表達式,需要用到AOP里的PARSER了。
最后匹配方法的時候,要么全MATCH 就OK,其他都返回FALSE。
這個類的大多數(shù)代碼,都是參考著org.springframework.aop.aspectj.AspectJExpressionPointcut
來寫
然后做了簡化如下
public class AspectJExpressionPointcut implements PointCut,ClassFilter,MethodMatcher {
private String expression;
private PointcutParser pointCutParser;
private PointcutExpression pointcutExpression;
public AspectJExpressionPointcut() {
pointCutParser = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();
}
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
@Override
public boolean matches(Class targetClass) {
checkReady();
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
private void checkReady() {
if(pointcutExpression == null)
pointcutExpression = pointCutParser.parsePointcutExpression(expression);
}
@Override
public boolean matches(Method method, Class targetClass) {
checkReady();
ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
if (shadowMatch.alwaysMatches()) {
return true;
}
return false;
}
@Override
public ClassFilter getClassFilter() {
return this;
}
@Override
public MethodMatcher getMethodMatcher() {
return this;
}
}
然后實現(xiàn)下AspectJExpressionPointcutAdvisor
這個類,主要就是對外提供ADVICE,和我們前面實現(xiàn)好的POINTCUT
public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor {
private AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
private Advice advice;
public void setAdvice(Advice advice) {
this.advice = advice;
}
public void setExpression(String expression) {
this.pointcut.setExpression(expression);
}
@Override
public PointCut getPointCut() {
return pointcut;
}
@Override
public Advice getAdvice() {
return advice;
}
}
下面測試,
當然你可以學一下ASPECTJ EXPRESION,寫出更多表達式來測試。
http://sishuok.com/forum/posts/list/281.html

Step4 實現(xiàn)融入Bean的創(chuàng)建過程,實現(xiàn)自己的BEAN POST PROCESSOR邏輯
現(xiàn)在我們有了Pointcut和Weave技術,一個AOP已經(jīng)算是完成了,但是它還沒有結合到Spring中去。怎么進行結合呢?Spring給了一個巧妙的答案:使用BeanPostProcessor。
BeanPostProcessor是BeanFactory提供的,在Bean初始化過程中進行擴展的接口。只要你的Bean實現(xiàn)了BeanPostProcessor接口,那么Spring在初始化時,會優(yōu)先找到它們,并且在Bean的初始化過程中,調用這個接口,從而實現(xiàn)對BeanFactory核心無侵入的擴展。
那么我們的AOP是怎么實現(xiàn)的呢?我們知道,在AOP的xml配置中,我們會寫這樣一句話:
<aop:aspectj-autoproxy/>
它其實相當于:
<bean id="autoProxyCreator" class="org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator"></bean>
AspectJAwareAdvisorAutoProxyCreator就是AspectJ方式實現(xiàn)織入的核心。它其實是一個BeanPostProcessor。在這里它會掃描所有Pointcut,并對bean做織入。
先定義出BEAN POST PROCESSOR 這個接口
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception;
Object postProcessAfterInitialization(Object bean, String beanName) throws Exception;
}
隨后根據(jù)我們上篇文章的分析,在實例化BEAN前,要把這個PROCESSOR給注冊上去。
所以我們找到AbstractApplicationContext 的 refresh方法 開始加上一步
隨后我們要在BEAN FACTORY 里維護所有的BEAN POST PROCESSOR
隨后在BEAN 完成doCreateBean() 后 ,還需要做一個initializeBean()
更新后的BEAN FACTORY
1。實現(xiàn)2個新方法
第一個方法是為了提前找到并且初始化一些特定CLASS TYPE的BEAN
第二個就是維護所有的BEAN POST PROCESSOR 的BEAN
public List getBeansForType(Class<?> type) throws Exception {
List beans = new ArrayList<Object>();
for (String beanDefinitionName : beanDefinitionMap.keySet()) {
if (type.isAssignableFrom(beanDefinitionMap.get(beanDefinitionName).getBeanClass())) {
beans.add(getBean(beanDefinitionName));
}
}
return beans;
}
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
beanPostProcessors.add(beanPostProcessor);
}
隨后
修改這邊
@Override
public Object getBean(String beanName) throws Exception {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition == null)
throw new IllegalArgumentException("No bean named " + beanName + " is defined");
Object bean = beanDefinition.getBean();
if(bean == null){
bean = doCreateBean(bean,beanDefinition);
bean = initializeBean(bean, beanName);
beanDefinition.setBean(bean);
}
return bean;
}
private Object initializeBean(Object bean, String beanName) throws Exception {
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
}
// TODO:call initialize method
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName);
}
return bean;
}
完整代碼
public abstract class AbstractBeanFactory implements BeanFactory {
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
@Override
public Object getBean(String beanName) throws Exception {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition == null)
throw new IllegalArgumentException("No bean named " + beanName + " is defined");
Object bean = beanDefinition.getBean();
if(bean == null){
bean = doCreateBean(bean,beanDefinition);
bean = initializeBean(bean, beanName);
beanDefinition.setBean(bean);
}
return bean;
}
private Object initializeBean(Object bean, String beanName) throws Exception {
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
}
// TODO:call initialize method
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName);
}
return bean;
}
protected abstract Object doCreateBean(Object bean, BeanDefinition beanDefinition) throws Exception;
public void preInstantiateSingletons() throws Exception {
for(String name : beanDefinitionMap.keySet())
getBean(name);
}
public void registerBeanDefinition(String key, BeanDefinition value) {
beanDefinitionMap.put(key, value);
}
public List getBeansForType(Class<?> type) throws Exception {
List beans = new ArrayList<Object>();
for (String beanDefinitionName : beanDefinitionMap.keySet()) {
if (type.isAssignableFrom(beanDefinitionMap.get(beanDefinitionName).getBeanClass())) {
beans.add(getBean(beanDefinitionName));
}
}
return beans;
}
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
beanPostProcessors.add(beanPostProcessor);
}
}
增加ABSTRACT APPLICATION CONTEXT 邏輯
public abstract class AbstractApplicationContext implements ApplicationContext {
protected AbstractBeanFactory beanFactory;
public AbstractApplicationContext(AbstractBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public void refresh() throws Exception {
loadBeanDefinitions();
registerBeanPostProcessors(beanFactory); // new added
finishBeanFactoryInitialization();
}
private void registerBeanPostProcessors(AbstractBeanFactory beanFactory) throws Exception {
List beanPostProcessors = beanFactory.getBeansForType(BeanPostProcessor.class);
for (Object beanPostProcessor : beanPostProcessors) {
beanFactory.addBeanPostProcessor((BeanPostProcessor) beanPostProcessor);
}
}
protected void finishBeanFactoryInitialization() throws Exception {
beanFactory.preInstantiateSingletons();
}
protected abstract void loadBeanDefinitions() throws Exception;
@Override
public Object getBean(String beanName) throws Exception {
return beanFactory.getBean(beanName);
}
}
Step5 開始實現(xiàn)一開始新建出來一直沒實現(xiàn)的BEAN AspectJAwareAdvisorAutoProxyCreator
在實現(xiàn)前,我們再理一下整個流程。
- AutoProxyCreator(實現(xiàn)了 BeanPostProcessor 接口)在實例化所有的 Bean 前,最先被實例化。因為registerBeanPostProcessor 在 finishInitiliazingBean 之前。
2.這個時候,他被BEAN FACTORY 通過getBeansForType 找到,并且調用了getBean(beanDefinitionName),最先實例化。
3.隨后在getBEAN實例化的時候,他會先doCreateBean,這個時候,他就應該把BEAN FACTORY 給注冊進去。因為之后要做postProcessAfterInitialization,來找到所有的切面我們需要用到BEAN FACTORY。
為了實現(xiàn)這個效果。我們搞一個接口出來。
public interface BeanFactoryAware {
public void setBeanFactory(BeanFactory beanFactory);
}
讓AutoProxyCreator實現(xiàn)一下。
隨后在doCreateBean 的 applyProPertyValues,注入BEAN FACTORY。
代碼如下
private void applyProPertyValues(Object bean, BeanDefinition beanDefinition) throws Exception {
if(bean instanceof BeanFactoryAware){
((BeanFactoryAware) bean).setBeanFactory(this);
}
PropertyValues propertyValues = beanDefinition.getPropertyValues();
....
隨后要實現(xiàn)BeanPostProcessor 的2個方法。
我們在后置處理器里實現(xiàn)的效果應該是,找到所有‘切面通知BEAN’(實現(xiàn)了這個AspectJExpressionPointcutAdvisor )或者‘’增強方法BEAN’(實現(xiàn)了這個MethodInterceptor),隨后依次加載他們。因為他們不要被代理,所以直接RETURN。
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
if (bean instanceof AspectJExpressionPointcutAdvisor) {
return bean;
}
if (bean instanceof MethodInterceptor) {
return bean;
}
List<AspectJExpressionPointcutAdvisor> advisors = beanFactory
.getBeansForType(AspectJExpressionPointcutAdvisor.class);
...
其他普通 Bean 被實例化、初始化,在初始化的過程中,AutoProxyCreator 加載 BeanFactory 中所有的 PointcutAdvisor(這也保證了 PointcutAdvisor 的實例化順序優(yōu)于普通 Bean。),然后依次使用 PointcutAdvisor 內(nèi)置的 ClassFilter,判斷當前對象是不是要攔截的類。
如果是,則生成一個 TargetSource(要攔截的對象和其類型),并取出 AutoProxyCreator 的 MethodMatcher(對哪些方法進行攔截)、Advice(攔截的具體操作),再,交給 AopProxy 去生成代理對象。
//繼續(xù)上面的代碼
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
if (advisor.getPointCut().getClassFilter().matches(bean.getClass())) {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
advisedSupport.setMethodMatcher(advisor.getPointCut().getMethodMatcher());
//這里往AdvisedSupport 多加個MethodMatcher屬性
TargetSource targetSource = new TargetSource(bean, bean.getClass(),bean.getClass().getInterfaces());
advisedSupport.setTargetSource(targetSource);
return new JdkDynamicAopProxy(advisedSupport).getProxy();
}
}
return bean;
}
- AopProxy 生成一個 InvocationHandler,在它的 invoke 函數(shù)中,首先使用 MethodMatcher 判斷是不是要攔截的方法,如果是則交給 Advice 來執(zhí)行(Advice 由用戶來編寫,其中也要手動/自動調用原始對象的方法),如果不是,則直接交給 TargetSource 的原始對象來執(zhí)行。
修改JDKDynamicProxy代碼
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInterceptor methodInterceptor = advisedSupport.getMethodInterceptor();
if (advisedSupport.getMethodMatcher() != null
&& advisedSupport.getMethodMatcher().matches(method, advisedSupport.getTargetSource().getTarget().getClass())) {
return methodInterceptor.invoke(new ReflectiveMethodInvocation(advisedSupport.getTargetSource().getTarget(),
method, args));
} else {
return method.invoke(advisedSupport.getTargetSource().getTarget(), args);
}
}
總結:
BeanPostProcessor :在 postProcessorAfterInitialization 方法中,使用動態(tài)代理的方式,返回一個對象的代理對象。解決了 在 IoC 容器的何處植入 AOP 的問題。
BeanFactoryAware :這個接口提供了對 BeanFactory 的感知,這樣,盡管它是容器中的一個 Bean,卻可以獲取容器的引用,進而獲取容器中所有的切點對象,決定對哪些對象的哪些方法進行代理。解決了 為哪些對象提供 AOP 的植入 的問題。
打開XML的AOP的注釋
開始測試
出錯了
java.lang.IllegalArgumentException: Can not set com.myspring.OutputService field com.myspring.HelloWorldServiceImpl.outputService to com.sun.proxy.$Proxy2
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
at java.lang.reflect.Field.set(Field.java:758)
at com.myspring.context.AutowireCapableBeanFactory.applyProPertyValues(AutowireCapableBeanFactory.java:40)
at com.myspring.context.AutowireCapableBeanFactory.doCreateBean(AutowireCapableBeanFactory.java:13)
at com.myspring.context.AbstractBeanFactory.getBean(AbstractBeanFactory.java:24)
at com.myspring.context.AbstractBeanFactory.preInstantiateSingletons(AbstractBeanFactory.java:49)
at com.myspring.context.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:28)
at com.myspring.context.AbstractApplicationContext.refresh(AbstractApplicationContext.java:17)
at com.myspring.context.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:19)
at com.myspring.context.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:13)
at test.HelloWorldServiceImplTest.helloWorld(HelloWorldServiceImplTest.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
猜測是JDK 動態(tài)代理沒法代理非接口的OutputService
所以把這個改成接口,成功了。

Step6 我們不要接口,用CGLIB 來代理實現(xiàn)下吧
用一個代理工廠來智能選擇代理
public interface AopProxy {
Object getProxy();
}
代理工廠,如果一個代理類有接口 就用JDK動態(tài)代理。否則就用CGLIB動態(tài)代理。
public class ProxyFactory extends AdvisedSupport implements AopProxy {
@Override
public Object getProxy() {
return createAopProxy().getProxy();
}
protected final AopProxy createAopProxy() {
if(getTargetSource().getInterfaces() == null || getTargetSource().getInterfaces().length == 0)
return new Cglib2AopProxy(this);
return new JdkDynamicAopProxy(this);
}
}
根據(jù)上一章的知識,這邊不難看懂。
public class Cglib2AopProxy implements AopProxy {
AdvisedSupport advised;
public Cglib2AopProxy(AdvisedSupport advised) {
this.advised = advised;
}
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(advised.getTargetSource().getTargetClass());
enhancer.setInterfaces(advised.getTargetSource().getInterfaces());
enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
Object enhanced = enhancer.create();
return enhanced;
}
private static class DynamicAdvisedInterceptor implements MethodInterceptor {
private AdvisedSupport advised;
private org.aopalliance.intercept.MethodInterceptor delegateMethodInterceptor;
private DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
this.delegateMethodInterceptor = advised.getMethodInterceptor();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if (advised.getMethodMatcher() == null
|| advised.getMethodMatcher().matches(method, advised.getTargetSource().getTargetClass())) {
return delegateMethodInterceptor.invoke(new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy));
}
return new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy).proceed();
}
}
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
private final MethodProxy methodProxy;
public CglibMethodInvocation(Object target, Method method, Object[] args, MethodProxy methodProxy) {
super(target, method, args);
this.methodProxy = methodProxy;
}
@Override
public Object proceed() throws Throwable {
return this.methodProxy.invoke(this.getThis(), this.getArguments());
}
}
}
最后修改AspectJAwareAdvisorAutoProxyCreator的這里
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
if (advisor.getPointCut().getClassFilter().matches(bean.getClass())) {
ProxyFactory advisedSupport = new ProxyFactory();
advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
advisedSupport.setMethodMatcher(advisor.getPointCut().getMethodMatcher());
TargetSource targetSource = new TargetSource(bean, bean.getClass(),bean.getClass().getInterfaces());
advisedSupport.setTargetSource(targetSource);
return advisedSupport.getProxy();
}
}
return bean;
去掉OUTPUTSERVICE 這個接口
測試成功,OUTPUT SERVICE 由CGLIB 動態(tài)代理
HELLO WORLD SERVICE 由JDK動態(tài)代理
