比较下spring 拦截器,一般有两种,第一种是使用 ProxyFactoryBean, 第二种是使用BeanNameAutoProxyCreator。先介绍这两种拦截器的简单使用例子,再比较分析优缺点.
使用 ProxyFactoryBean 作拦截器三部曲
1.先定义业务接口以及实现类(无需实现或扩展任何接口或继承类)
//业务接口
public interface SayHello
{
public void sayHell();
}
//业务接口实现类之一
public class SayChineseHelloImpl implements SayHello
{
/* (non-Javadoc)
* @see test.SayHello#sayHell()
*/
public void sayHell()
{
PrintUtil.print("你好!");
}
}
//业务实现接口类之二
public class SayEnglishHello implements SayHello
{
/* (non-Javadoc)
* @see test.SayHello#sayHell()
*/
public void sayHell()
{
PrintUtil.print("hello !");
}
}
2.定义拦截器(需实现MethodInterceptor 接口)
//定义日志拦截器
public class LogInterCeptor implementsMethodInterceptor
{
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public Object invoke(MethodInvocation invocation) throwsThrowable
{
doBusiness(invocation);
return invocation.proceed();
}
private Object doBusiness(MethodInvocation invocation){
System.out.print("I'm do nothing except record log.....");
return null;
}
}
3.spring.xml 配置
<bean id="sayChineseHello"class="test.SayChineseHelloImpl"/>
<bean id="sayEnglishHello"class="test.SayEnglishHello"/>
<bean id="logInterceptor"class="interceptor.LogInterCeptor"/>
<bean id="sayHelloProxy"class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<!--需要拦截的接口的类全名-->
<value>test.SayHello</value>
</property>
<property name="interceptorNames">
<list>
<!--由拦截器和业务类组成的列表,业务类必须放在最后,而且只能拦截一个业务类-->
<value>logInterceptor</value>
<value>sayEnglishHello</value>
</list>
</property>
</bean>
好了,至此,一切就绪,开始使用:
public class InterceptorTest
{
private ApplicationContext context=null;
@Before
public void init(){
context=newClassPathXmlApplicationContext("spring.xml");
}
@Test
public void testInterceptor(){
System.out.println("sayEnglishHello whitout proxy!");
SayHello sayEnglishHello=(SayHello) context.getBean("sayEnglishHello");
sayEnglishHello.sayHell();
System.out.println("sayChineseHello whitout proxy!");
SayHello sayChineseHello=(SayHello) context.getBean("sayChineseHello");
sayChineseHello.sayHell();
System.out.println("sayEnglishHello whit proxy!");
SayHello sayHelloProxy=(SayHello) context.getBean("sayHelloProxy");
sayHelloProxy.sayHell();
}
}
输出结果
sayEnglishHello whitout proxy!
hello!
sayChineseHello whitout proxy!
你好!
sayEnglishHello whit proxy!
I'm nothing except record log.....
hello!
BeanNameAutoProxyCreator 跟上面差不多,只是配置不同而已:
<bean id="sayChineseHello"class="test.SayChineseHelloImpl"/>
<bean id="sayEnglishHello"class="test.SayEnglishHello"/>
<bean id="logInterceptor"class="interceptor.LogInterCeptor"/>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"id="test_proxy">
<property name="beanNames">
<list>
<!--需要拦截的业务类ID列表-->
<value>sayEnglishHello</value>
<value>sayChineseHello</value>
</list>
</property>
<property name="interceptorNames">
<list>
<!--拦截器列表-->
<value>logInterceptor</value>
</list>
</property>
</bean>
public class InterceptorTest
{
private ApplicationContext context=null;
@Before
public void init(){
context=new ClassPathXmlApplicationContext("spring.xml");
}
@Test
public void testInterceptor(){
System.out.println("sayEnglishHello whit BeanNameAutoProxyCreator!");
SayHello sayEnglishHello=(SayHello) context.getBean("sayEnglishHello");
sayEnglishHello.sayHell();
System.out.println("sayChineseHello whit BeanNameAutoProxyCreator!");
SayHello sayChineseHello=(SayHello) context.getBean("sayChineseHello");
sayChineseHello.sayHell();
}
}
sayEnglishHello whit BeanNameAutoProxyCreator!
I'm nothing except record log.....
hello!
sayChineseHello whit BeanNameAutoProxyCreator!
I'm nothing except record log.....
你好!
总结下:两种拦截器都需要经过三个步骤:实现业务类,实现拦截器,配置业务类也拦截器关系。如果需要代理的bean很多,使用ProxyFactoryBean 无疑会对spring配置文件的编写带来繁重的工作,因为ProxyFactoryBean 不支持代理列表。BeanNameAutoProxyCreator考虑到这点,既支持多个拦截器,又支持多个代理bean,略胜一筹,哈哈
事务管理配置
<?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="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/myuser</value>
</property>
<property name="username">
<value>lighter</value>
</property>
<property name="password">
<value>12345</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>org/mmc/dao/domain/User.hbm.xml</value>
</list>
</property>
</bean>
<!-- 配置Hibernate的事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 定义事务拦截器bean -->
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 定义BeanNameAutoProxyCreator-->
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<!-- 所有名字以DAO,Service结尾的bean,将由该"bean后处理器"为其创建事务代理;实际上应该在业务层进行事务管理,这里只是举一个简单例子 -->
<value>*DAO,*Service</value>
</property>
<!-- 下面定义BeanNameAutoProxyCreator所需的事务拦截器-->
<property name="interceptorNames">
<list>
<!-- 可以增加其他的拦截器 -->
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!-- 举下面这一个例子:这时候,这一个bean已经有了事务管理,可以增加类似的bean -->
<bean id="searchUserDAO" class="org.mmc.dao.impl.SearchUserDAO">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
ref:http://my.oschina.net/qicheng/blog/168085