提到代理,我们可以使用ProxyBeanFactory,并配置proxyInterfaces,target和interceptorNames实现,但如果需要代理的bean很多,无疑会对spring配置文件的编写带来繁重的工作
Spring为我们提供了,根据beanName匹配后进行自动代理的解决方法
业务接口
public interface Shopping {
public String buySomething(String type);
public String buyAnything(String type);
public String sellSomething(String type);
public String sellAnything(String type);
}
业务实现类A,作为配置文件中的buyBean:
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 ;
}
}
业务实现类B,作为配置文件中的sellBean:
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 ;
}
}
切面通知:
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 " );
}
}
配置文件:
其中beanNames为buy*,意味着所有以buy开头的bean,都被spring容易自动代理,执行相应的切面通知
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
< bean id ="WelcomeAdvice" class ="AutoProxyOne.WelcomeAdvice" >
</ bean >
< bean class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
< property name ="beanNames" >
< list >
< value > buy* </ value >
</ list >
</ property >
< property name ="interceptorNames" >
< list >
< value > WelcomeAdvice </ value >
</ list >
</ property >
</ bean >
< bean id ="buyBean" class ="AutoProxyOne.ShoppingImplA" >
< property name ="customer" >
< ref bean ="customer" />
</ property >
</ bean >
< bean id ="sellBean" class ="AutoProxyOne.ShoppingImplB" >
< property name ="customer" >
< ref bean ="customer" />
</ property >
</ bean >
< bean id ="customer" class ="AutoProxyOne.Customer" >
< constructor-arg index ="0" >
< value > gaoxiang </ value >
</ constructor-arg >
< constructor-arg index ="1" >
< value > 26 </ value >
</ constructor-arg >
</ bean >
</ beans >
测试代码:
在测试代码中,我们的buyBean打印两条买的信息,sellBean打印两条卖的信息,可以看到buyBean执行的方法已经进行了切面处理
需要注意的是,如果使用自动代码,则获得Spring Bean工厂要用
ApplicationContext ctx=new FileSystemXmlApplicationContext(filePath);
而不能用
BeanFactory factory=new XmlBeanFactory(new FileSystemResource(filePath));
原因我想是因为BeanFactory在初始化时并不实例化单例的Bean,而ApplicationContext则在初始化时候全部实例化了Bean,自动代理需要在初始化时候定义好代理关系
import java.io.File;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.aop.support.RegexpMethodPointcutAdvisor;
public class TestAdvisor {
public static void main(String[] args) {
String filePath = System.getProperty( " user.dir " ) + File.separator + " AutoProxyOne " + File.separator + " hello.xml " ;
BeanFactory factory = new XmlBeanFactory( new FileSystemResource(filePath));
ApplicationContext ctx = new FileSystemXmlA