DefaultAdvisorAutoProxyCreator这个类功能更为强大,这个类的奇妙之处是他实现了BeanProcessor接口,当ApplicationContext读如所有的Bean配置信息后,这个类将扫描上下文,寻找所有的Advistor(一个Advisor是一个切入点和一个通知的组成),将这些Advisor应用到所有符合切入点的Bean中。
工程结构图:
业务接口:
package com.bijian.study; public interface Shopping { public String buySomething(String type); public String buyAnything(String type); public String sellSomething(String type); public String sellAnything(String type); }
业务实现类:
package com.bijian.study; public class ShoppingImplA implements Shopping { private Customer customer; public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public String buySomething(String type) { System.out.println(this.getCustomer().getName()+" bye "+type+" success"); return null; } public String buyAnything(String type) { System.out.println(this.getCustomer().getName()+" bye "+type+" success"); return null; } public String sellAnything(String type) { System.out.println(this.getCustomer().getName()+" sell "+type+" success"); return null; } public String sellSomething(String type) { System.out.println(this.getCustomer().getName()+" sell "+type+" success"); return null; } }
package com.bijian.study; public class ShoppingImplB implements Shopping { private Customer customer; public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public String buySomething(String type) { System.out.println(this.getCustomer().getName()+" bye "+type+" success"); return null; } public String buyAnything(String type) { System.out.println(this.getCustomer().getName()+" bye "+type+" success"); return null; } public String sellAnything(String type) { System.out.println(this.getCustomer().getName()+" sell "+type+" success"); return null; } public String sellSomething(String type) { System.out.println(this.getCustomer().getName()+" sell "+type+" success"); return null; } }
通知:
package com.bijian.study; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; //前置通知 public class WelcomeAdvice implements MethodBeforeAdvice { public void before(Method method, Object[] args, Object obj) throws Throwable { System.out.println("Hello welcome to bye "); } }
普通Bean类:
package com.bijian.study; public class Customer { private String name; private int age; public Customer(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } }
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="WelcomeAdvice" class="com.bijian.study.WelcomeAdvice"></bean> <!-- 自动代理所有的advisor --> <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> </bean> <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="pattern"> <value>.*sell.+</value> <!-- 业务实现方法名匹配 --> </property> <property name="advice"> <ref bean="WelcomeAdvice" /> </property> </bean> <bean id="buyBean" class="com.bijian.study.ShoppingImplA"> <property name="customer"> <ref bean="customer" /> </property> </bean> <bean id="sellBean" class="com.bijian.study.ShoppingImplB"> <property name="customer"> <ref bean="customer" /> </property> </bean> <bean id="customer" class="com.bijian.study.Customer"> <constructor-arg index="0"> <value>gaoxiang</value> </constructor-arg> <constructor-arg index="1"> <value>26</value> </constructor-arg> </bean> </beans>
我们配置一个advisor,方法和在我的blog关于静态切入点的用正则表达式配置切入点相同,这里匹配的是业务实现类中所有型如:***sell***的方法。
buyBean和sellBean是最为普通的IOC配置,重点在autoProxyCreator中,我们只需配置一个id(id非必需)和class,spring会自动帮我们解析advisor,并将通知进行切入。
测试程序:
package com.bijian.study.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.bijian.study.Shopping; public class TestAdvisor { public static void main(String[] args) { // String filePath=System.getProperty("user.dir")+File.separator+"src"+File.separator+"applicationContext.xml"; // ApplicationContext ctx=new FileSystemXmlApplicationContext(filePath); ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Shopping shoppingA=null; Shopping shoppingB=null; shoppingA=(Shopping)ctx.getBean("buyBean"); shoppingB=(Shopping)ctx.getBean("sellBean"); shoppingA.buySomething("something"); shoppingA.buyAnything("anything"); shoppingB.sellAnything("anything"); shoppingB.sellSomething("something"); } }
需要注意的是:和BeanNameAutoProxyCreator相同,我们需要用ApplicationContext获得Bean。运行结果:
gaoxiang bye something success gaoxiang bye anything success Hello welcome to bye gaoxiang sell anything success Hello welcome to bye gaoxiang sell something success
可以看到我们定义的所有***sell***的方法,都被切入了前置通知。
PS:在执行时如报java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice错,是少了aopalliance包,这个包涉及到动态织入。是spring的常用联盟包,必不可少。