Advice只有切面化之后才能显现出AOP的巨大优势

上一篇所讲到的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);
  }
}
 
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 ;
    }
  }
}
 
配置文件:
<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);
 
运行结果:
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====
 
不过这里有个问题,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>
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值