上一篇所講到的Advice,經過ProxyFactoryBean織入到Bean中,實際上是織入到Bean的聯接點上,這顯然不是我們想看到的,因為并不是所有方法都需要同樣的公用代碼。spring提供了切點(Pointcut)的概念,指真正需要織入Advice的聯接點,并且提供了專門的類org.springframework.aop.support.NameMatchMethodPointcutAdvisor把Advice和Pointcut結合成一個整體,叫切面(Advisor),這樣對Bean的方法就可以有選擇的進行處理。是以,Advice隻有切面化之後才能顯現出AOP的巨大優勢。
比如,我們對Dao類進行添加事務的處理,顯然隻有增,删,改才需要,而查詢方法就不再需要。
Dao類:
public class StudentDaoImpl implements StudentDao {
@Override
public void delete(Integer id) {//事務處理已經被提取出去了
Student stu=getStudentById(id);
Session session=HibernateUtil.getCurrentSession();
session.delete(stu);
}
public Student getStudentById(Integer id) {//查詢不需要事務
Session session=HibernateUtil.openSession();
Student stu=(Student)session.get(Student.class, id);
return stu;
@SuppressWarnings("unchecked")
public List<Student> getStudents() {//查詢不需要事務
String hql="from Student";
List<Student> stus=session.createQuery(hql).list();
return stus;
public void insert(Student stu) {//事務處理已經被提取出去了
session.save(stu);
public void modify(Student stu) {//事務處理已經被提取出去了
session.saveOrUpdate(stu);
}
Advice:
public class TransactionAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
try{
Transaction trans=session.beginTransaction();
trans.begin();
System.out.println("====begin transaction====");
Object ret=invocation.proceed();
trans.commit();
System.out.println("====commit transaction====");
return ret;
}catch(Exception e){
HibernateUtil.getCurrentSession().getTransaction().rollback() ;
System.out.println( "**** rollback transaction ****") ;
throw e ;
}
配置檔案:
<beans>
<bean id="targetDao" class="com.yangfei.spring.advisor.dao.StudentDaoImpl"></bean>
<bean id="transAdvice" class="com.yangfei.spring.advisor.advice.TransactionAdvice"></bean>
<bean id="transAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<ref local="transAdvice"/>
</property>
<property name="mappedNames">
<list>
<value>insert</value>
<value>delete</value>
<value>modify</value>
</list>
</bean>
<bean id="dao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref bean="targetDao"/>
<property name="interceptorNames">
<value>transAdvisor</value>
<property name="interfaces">
<list>
<value>com.yangfei.spring.advisor.dao.StudentDao</value>
</list>
</property>
</beans>
測試:
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
StudentDao dao=(StudentDao)ctx.getBean("dao");
//查
Student stu=dao.getStudentById(2);
System.out.println(stu);
List<Student> stus=dao.getStudents();
for(Student s:stus){
System.out.println(s);
/*
dao.delete(4);
Student s=new Student();
s.setName("wangwu");
s.setBirthday(new Date());
dao.insert(s);*/
Student s=new Student();
s.setId(4);
s.setName("zhaoliu");
s.setBirthday(new Date());
dao.modify(s);
運作結果:
Hibernate: select student0_.id as id0_0_, student0_.name as name0_0_, student0_.birthday as birthday0_0_ from spring_student student0_ where student0_.id=?
Student: zhangsan
Hibernate: select student0_.id as id0_, student0_.name as name0_, student0_.birthday as birthday0_ from spring_student student0_
Student: yangfei
Student: lisi
Student: zhaoliu
====begin transaction====
Hibernate: delete from spring_student where id=?
====commit transaction====
Hibernate: select max(id) from spring_student
Hibernate: insert into spring_student (name, birthday, id) values (?, ?, ?)
Hibernate: update spring_student set name=?, birthday=? where id=?
不過這裡有個問題,ProxyFactoryBean一次隻能給一個Bean織入切面,如果我們Bean要足夠多的話,顯然會把配置檔案搞的非常龐大。幸運的是spring還提供了另一個類org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator,可以一次給多個Bean配置多個Advisor。當然,在使用Bean時,就不能直接用它BeanNameAutoProxyCreator的id了,而隻能使用Bean各自的id,取出來的就是代理對象了。
<bean id="targetDao2" class="com.yangfei.spring.advisor.dao.StudentDaoImpl"></bean>
<bean id="test" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<value>targetDao</value>
<value>targetDao2</value>
本文轉自NightWolves 51CTO部落格,原文連結:http://blog.51cto.com/yangfei520/246283,如需轉載請自行聯系原作者