ProxyFactoryBean 是最原始的实现Spring AOP配置的方式
实例:
<bean id="testDaoService" class="com.daodao.mybatis.testDaoService"/>
<bean id="testAOPAdvice" class="com.daodao.mybatis.testAOPAdvice"/>
<bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
p:advice-ref="testAOPAdvice">
<property name="patterns">
<list>
<value>com\.daodao\.mybatis\..*</value>
</list>
</property>
</bean>
<bean id="aoptest1" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="regexpAdvisor"
p:target-ref="testDaoService"
p:proxyTargetClass="true"/>
实例化过程主要类:
1.ProxyFactoryBean
2.RegexpMethodPointcutAdvisor
3.DefaultAopProxyFactory
4.JdkDynamicAopProxy+ObjenesisCglibAopProxy
1.ProxyFactoryBean 继承FactoryBean接口,getObject()方法在实例化bean的时候被调用,返回值为代理对象
a. getObject()方法首先initializeAdvisorChain(); 将RegexpMethodPointcutAdvisor添加至ProxyFactoryBean的advisors
b. 非prototype时调用getSingletonInstance();将自己作为参数传给DefaultAopProxyFactory.createAopProxy(AdvisedSupport config)去创建代理对象。
2.DefaultAopProxyFactory 根据传输的AdvisedSupport的一些条件判定采用ObjenesisCglibAopProxy(AdvisedSupport config)还是JdkDynamicAopProxy(AdvisedSupport config)
3.JdkDynamicAopProxy 继承自 AopProxy接口的getProxy()方法被调用,Proxy.newProxyInstance(classLoader, proxiedInterfaces, this).其中this就是当前的JdkDynamicAopProxy(继承自InvocationHandler.).需要注意的是,JdkDynamicAopProxy持有了ProxyFactoryBean对象,间接的拥有了advisors,target.
4.ObjenesisCglibAopProxy 与3类似,实现是基于cglib
运行过程主要接口:
1.MethodInterceptor(实现类com.daodao.mybatis.testAOPAdvice)
2.MethodInvocation(实现类ReflectiveMethodInvocation)
1. JdkDynamicAopProxy 的invoke(Object proxy, Method method, Object[] args)会调用ReflectiveMethodInvocation.proceed();来处理整个流程
a.ReflectiveMethodInvocation 最终目的是将增强逻辑依次插入到现有方法实现的前后。其过程是先调用所有的MethodInterceptor的invoke(MethodInvocation invocation),该方法在实现中又会调用invocation.proceed();,直到所有的advice跑完,将会调用target的原有方法。是个递归调用。
总结:
仅对JDK动态代理来说,就是将所有的MethodInterceptor实现类和target被代理的类交给InvocationHandler,在InvocationHandler的invoke(Object proxy, Method method, Object[] args)调用中嵌套调用最终跑完所有的MethodInterceptor的invoke(MethodInvocation invocation)以及target的原本方法。