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 >
      本文转自NightWolves 51CTO博客,原文链接:http://blog.51cto.com/yangfei520/246283 ,如需转载请自行联系原作者
相关文章
|
7月前
|
XML 缓存 监控
切面的魔力:解密Spring AOP 面向切面编程
切面的魔力:解密Spring AOP 面向切面编程
29 0
|
3月前
|
缓存 Java Spring
Spring 源码阅读 66:基于 JDK 的 AOP 代理如何获取拦截器链(4)- 将 Advice 封装为拦截器
【1月更文挑战第1天】本文分析了 Advice 被封装成 MethodInterceptor 的过程,Spring AOP 用到的五种 Advice 中,有些本身就是 MethodInterceptor 的实现类,而有些需要通过适配器的封装。
41 0
|
Java API Spring
史上最全AOP 切面表达式,看完逼格有提升了
史上最全AOP 切面表达式,看完逼格有提升了。源码已放开头了,请你查收。
808 0
|
1月前
|
存储 数据可视化 Java
自定义注解实现aop切面
自定义注解实现aop切面
23 1
|
2月前
|
Java Spring
Spring5源码(28)-Aop知识点回顾以及基于Advice接口的增强实现
Spring5源码(28)-Aop知识点回顾以及基于Advice接口的增强实现
30 0
|
3月前
|
Dubbo Java 应用服务中间件
微服务框架(八)Spring Boot AOP 日志切面实现
  此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。   本文为使用Spring Boot AOP 实现日志切面、分离INFO和ERROR级别日志
|
5月前
|
缓存 监控 安全
深入理解Spring Boot AOP:切面编程的优势与应用
深入理解Spring Boot AOP:切面编程的优势与应用
|
5月前
|
Java Maven Spring
AOP切面编程
AOP(Aspect Oriented Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程的一种补充和完善,它以通过预编译方式和运行期动态代理方式实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。
51 0
|
6月前
|
Java API Spring
Advice在Spring AOP中对应API
Advice在Spring AOP中对应API
18 0
|
8月前
|
XML Java 程序员
spring AOP切面编程
spring AOP切面编程
94 0