上一篇所讲到的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);
}
@Override
public Student getStudentById(Integer id) { //查询不需要事务
Session session=HibernateUtil.openSession();
Student stu=(Student)session.get(Student. class, id);
return stu;
}
@SuppressWarnings( "unchecked")
@Override
public List<Student> getStudents() { //查询不需要事务
Session session=HibernateUtil.openSession();
String hql= "from Student";
List<Student> stus=session.createQuery(hql).list();
return stus;
}
@Override
public void insert(Student stu) { //事务处理已经被提取出去了
Session session=HibernateUtil.getCurrentSession();
session.save(stu);
}
@Override
public void modify(Student stu) { //事务处理已经被提取出去了
Session session=HibernateUtil.getCurrentSession();
session.saveOrUpdate(stu);
}
}
@Override
public void delete(Integer id) { //事务处理已经被提取出去了
Student stu=getStudentById(id);
Session session=HibernateUtil.getCurrentSession();
session.delete(stu);
}
@Override
public Student getStudentById(Integer id) { //查询不需要事务
Session session=HibernateUtil.openSession();
Student stu=(Student)session.get(Student. class, id);
return stu;
}
@SuppressWarnings( "unchecked")
@Override
public List<Student> getStudents() { //查询不需要事务
Session session=HibernateUtil.openSession();
String hql= "from Student";
List<Student> stus=session.createQuery(hql).list();
return stus;
}
@Override
public void insert(Student stu) { //事务处理已经被提取出去了
Session session=HibernateUtil.getCurrentSession();
session.save(stu);
}
@Override
public void modify(Student stu) { //事务处理已经被提取出去了
Session session=HibernateUtil.getCurrentSession();
session.saveOrUpdate(stu);
}
}
Advice:
public
class TransactionAdvice
implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try{
Session session=HibernateUtil.getCurrentSession();
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 ;
}
}
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try{
Session session=HibernateUtil.getCurrentSession();
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 >
</ property >
</ bean >
< bean id ="dao" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="target" >
< ref bean ="targetDao" />
</ property >
< property name ="interceptorNames" >
< list >
< value >transAdvisor </ value >
</ list >
</ property >
< property name ="interfaces" >
< list >
< value >com.yangfei.spring.advisor.dao.StudentDao </ value >
</ list >
</ property >
</ bean >
</ 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 >
</ property >
</ bean >
< bean id ="dao" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="target" >
< ref bean ="targetDao" />
</ property >
< property name ="interceptorNames" >
< list >
< value >transAdvisor </ value >
</ list >
</ property >
< property name ="interfaces" >
< list >
< value >com.yangfei.spring.advisor.dao.StudentDao </ value >
</ list >
</ property >
</ bean >
</ 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);
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: zhangsan
Student: lisi
Student: zhaoliu
====begin transaction====
Hibernate: select student0_.id as id0_0_, student0_.name as name0_0_, student0_.birthday as birthday0_0_ from spring_student student0_ where student0_.id=?
Hibernate: delete from spring_student where id=?
====commit transaction====
====begin transaction====
Hibernate: select max(id) from spring_student
Hibernate: insert into spring_student (name, birthday, id) values (?, ?, ?)
====commit transaction====
====begin transaction====
Hibernate: update spring_student set name=?, birthday=? where id=?
====commit transaction====
Student: zhangsan
Hibernate: select student0_.id as id0_, student0_.name as name0_, student0_.birthday as birthday0_ from spring_student student0_
Student: yangfei
Student: zhangsan
Student: lisi
Student: zhaoliu
====begin transaction====
Hibernate: select student0_.id as id0_0_, student0_.name as name0_0_, student0_.birthday as birthday0_0_ from spring_student student0_ where student0_.id=?
Hibernate: delete from spring_student where id=?
====commit transaction====
====begin transaction====
Hibernate: select max(id) from spring_student
Hibernate: insert into spring_student (name, birthday, id) values (?, ?, ?)
====commit transaction====
====begin transaction====
Hibernate: update spring_student set name=?, birthday=? where id=?
====commit transaction====
不过这里有个问题,ProxyFactoryBean一次只能给一个Bean织入切面,如果我们Bean要足够多的话,显然会把配置文件搞的非常庞大。幸运的是spring还提供了另一个类org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator,可以一次给多个Bean配置多个Advisor。当然,在使用Bean时,就不能直接用它BeanNameAutoProxyCreator的id了,而只能使用Bean各自的id,取出来的就是代理对象了。
<
beans
>
< bean id ="targetDao" class ="com.yangfei.spring.advisor.dao.StudentDaoImpl" > </ bean >
< bean id ="targetDao2" 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 >
</ property >
</ bean >
< bean id ="test" class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
< property name ="interceptorNames" >
< list >
< value >transAdvisor </ value >
</ list >
</ property >
< property name ="beanNames" >
< list >
< value >targetDao </ value >
< value >targetDao2 </ value >
</ list >
</ property >
</ bean >
</ beans >
< bean id ="targetDao" class ="com.yangfei.spring.advisor.dao.StudentDaoImpl" > </ bean >
< bean id ="targetDao2" 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 >
</ property >
</ bean >
< bean id ="test" class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
< property name ="interceptorNames" >
< list >
< value >transAdvisor </ value >
</ list >
</ property >
< property name ="beanNames" >
< list >
< value >targetDao </ value >
< value >targetDao2 </ value >
</ list >
</ property >
</ bean >
</ beans >
本文转自NightWolves 51CTO博客,原文链接:http://blog.51cto.com/yangfei520/246283
,如需转载请自行联系原作者