Spring為我們提供了自動代理機制,讓容器為我們自動生成代理,把我們從煩瑣的配置工作中解放出來,在內部,Spring 使用BeanPostProcessor自動地完成這項工作。
1、實現類介紹
這些基於BeanPostProcessor的自動代理創建器的實現類,將根據一些規則自動在容器實例化Bean時為匹配的Bean生成代理實例。
1)基於Bean配置名規則的自動代理創建器:允許為一組特定配置名的Bean自動創建代理實例的代理創建器,實現類為BeanNameAutoProxyCreator;
2)基於Advisor匹配機制的自動代理創建器:它會對容器中所有的Advisor進行掃描,自動將這些切面應用到匹配的Bean中(即為目標Bean創建代理實例),實現類為DefaultAdvisorAutoProxyCreator;
3)基於Bean中AspjectJ注解標簽的自動代理創建器:為包含AspectJ注解的Bean自動創建代理實例,它的實現類是AnnotationAwareAspectJAutoProxyCreator,該類是Spring 2.0的新增類。
2、BeanNameAutoProxyCreator
Waiter業務類:
package com.yyq.aop; public class Waiter { public void greetTo(String name) { System.out.println("waiter greet to " + name + "."); } public void serveTo(String name) { System.out.println("waiter serving to " + name + "."); } }
Seller業務類:
package com.yyq.aop; public class Seller { public void greetTo(String name) { System.out.println("seller greet to " + name + "."); } }
GreetingBeforeAdvice前置增強實現類:
package com.yyq.aop; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class GreetingBeforeAdvice implements MethodBeforeAdvice { @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println(o.getClass().getName() + "." + method.getName()); String clientName = (String) objects[0]; System.out.println("Hi! Mr." + clientName + "."); } }
使用Bean名進行自動代理配置:
<bean id="waiterTarget" class="com.yyq.aop.Waiter"/> <bean id="sellerTarget" class="com.yyq.aop.Seller"/> <bean id="greetingAdvice" class="com.yyq.aop.GreetingBeforeAdvice"/> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" p:beanNames="*Target" p:interceptorNames="greetingAdvice" p:optimize="true"/>
BeanNameAutoProxyCreator 有一個beanNames屬性,它允許用戶指定一組需要自動代理的Bean名稱,Bean名稱可以使用 * 通配符。
測試方法:
@Test public void testAdvisor6(){ String configPath = "com\\yyq\\aop\\beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter)ctx.getBean("waiterTarget"); Seller seller = (Seller)ctx.getBean("sellerTarget"); waiter.greetTo("Peter"); seller.greetTo("Tom"); }
輸出結果:
com.yyq.aop.Waiter.greetTo
Hi! Mr.Peter.
waiter greet to Peter.
com.yyq.aop.Seller.greetTo
Hi! Mr.Tom.
seller greet to Tom.
3、DefaultAdvisorAutoProxyCreator
Advisor是切點和增強的復合體,Advisor本身已經包含了足夠的信息:橫切邏輯(要織入什么)以及連接點(織入到哪里)。DefaultAdvisorAutoProxyCreator能夠掃描容器中的Advisor,並將Advisor自動織入到匹配的目標Bean中,即為匹配的目標Bean自動創建代理。
配置:
<bean id="waiterTarget" class="com.yyq.aop.Waiter"/> <bean id="sellerTarget" class="com.yyq.aop.Seller"/> <bean id="greetingAdvice" class="com.yyq.aop.GreetingBeforeAdvice"/> <bean id="regexpAdvisor2" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" p:pattern=".*greet.*" p:advice-ref="greetingAdvice"/> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
測試方法:
@Test public void testAdvisor7(){ String configPath = "com\\yyq\\aop\\beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter)ctx.getBean("waiterTarget"); Seller seller = (Seller)ctx.getBean("sellerTarget"); waiter.greetTo("Peter"); waiter.serveTo("Peter"); seller.greetTo("Tom"); }
輸出結果:
com.yyq.aop.Waiter.greetTo
Hi! Mr.Peter.
waiter greet to Peter.
waiter serving to Peter.
com.yyq.aop.Seller.greetTo
Hi! Mr.Tom.
seller greet to Tom.
