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的常用联盟包,必不可少。