使用BeanNameAutoProxyCreator实现spring的自动代理
提到代理,我们可以使用ProxyBeanFactory,并配置proxyInterfaces,target和interceptorNames实现,但如果需要代理的bean很多,无疑会对spring配置文件的编写带来繁重的工作
Spring为我们提供了,根据beanName匹配后进行自动代理的解决方法
业务接口
publicinterfaceShopping...{
publicStringbuySomething(Stringtype);
publicStringbuyAnything(Stringtype);
publicStringsellSomething(Stringtype);
publicStringsellAnything(Stringtype);
}
业务实现类A,作为配置文件中的buyBean:
publicclassShoppingImplAimplementsShopping...{
privateCustomercustomer;
publicCustomergetCustomer()...{
returncustomer;
}
publicvoidsetCustomer(Customercustomer)...{
this.customer=customer;
}
publicStringbuySomething(Stringtype)...{
System.out.println(this.getCustomer().getName()+"bye"+type+"success");
returnnull;
}
publicStringbuyAnything(Stringtype)...{
System.out.println(this.getCustomer().getName()+"bye"+type+"success");
returnnull;
}
publicStringsellAnything(Stringtype)...{
System.out.println(this.getCustomer().getName()+"sell"+type+"success");
returnnull;
}
publicStringsellSomething(Stringtype)...{
System.out.println(this.getCustomer().getName()+"sell"+type+"success");
returnnull;
}
}
业务实现类B,作为配置文件中的sellBean:
publicclassShoppingImplBimplementsShopping...{
privateCustomercustomer;
publicCustomergetCustomer()...{
returncustomer;
}
publicvoidsetCustomer(Customercustomer)...{
this.customer=customer;
}
publicStringbuySomething(Stringtype)...{
System.out.println(this.getCustomer().getName()+"bye"+type+"success");
returnnull;
}
publicStringbuyAnything(Stringtype)...{
System.out.println(this.getCustomer().getName()+"bye"+type+"success");
returnnull;
}
publicStringsellAnything(Stringtype)...{
System.out.println(this.getCustomer().getName()+"sell"+type+"success");
returnnull;
}
publicStringsellSomething(Stringtype)...{
System.out.println(this.getCustomer().getName()+"sell"+type+"success");
returnnull;
}
}
切面通知:
importjava.lang.reflect.Method;
importorg.springframework.aop.MethodBeforeAdvice;
//前置通知
publicclassWelcomeAdviceimplementsMethodBeforeAdvice...{
publicvoidbefore(Methodmethod,Object[]args,Objectobj)
throwsThrowable...{
System.out.println("Hellowelcometobye");
}
}
配置文件:
其中beanNames为buy*,意味着所有以buy开头的bean,都被spring容易自动代理,执行相应的切面通知
<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<beanid="WelcomeAdvice"class="AutoProxyOne.WelcomeAdvice">
</bean>
<beanclass="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<propertyname="beanNames">
<list>
<value>buy*</value>
</list>
</property>
<propertyname="interceptorNames">
<list>
<value>WelcomeAdvice</value>
</list>
</property>
</bean>
<beanid="buyBean"class="AutoProxyOne.ShoppingImplA">
<propertyname="customer">
<refbean="customer"/>
</property>
</bean>
<beanid="sellBean"class="AutoProxyOne.ShoppingImplB">
<propertyname="customer">
<refbean="customer"/>
</property>
</bean>
<beanid="customer"class="AutoProxyOne.Customer">
<constructor-argindex="0">
<value>gaoxiang</value>
</constructor-arg>
<constructor-argindex="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,自动代理需要在初始化时候定义好代理关系
importjava.io.File;
importorg.springframework.beans.factory.BeanFactory;
importorg.springframework.beans.factory.xml.XmlBeanFactory;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
importorg.springframework.core.io.FileSystemResource;
importorg.springframework.aop.support.RegexpMethodPointcutAdvisor;
publicclassTestAdvisor...{
publicstaticvoidmain(String[]args)...{
StringfilePath=System.getProperty("user.dir")+File.separator+"AutoProxyOne"+File.separator+"hello.xml";
BeanFactoryfactory=newXmlBeanFactory(newFileSystemResource(filePath));
ApplicationContextctx=newFileSystemXmlA