Spring-AOP之aspectj注解方式

一、简介 1、AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理日志管理权限控制异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。 2、AOP中的概念: Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象. joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器) Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即joinpoint的集合. Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知 Target(目标对象):代理的目标对象 Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入. Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

3、AOP带来的好处::降低模块的耦合度;使系统容易扩展;更好的代码复用性

二、通过注解方式实现Spring的AOP

1.定义业务类

接口:

[java]

package cn.slimsmart.spring.demo.aop;  
 
public interface UserService {  
    String save(String name);  
    String update(String name);  
    String delete(String name);  
}  

实现:

[java]

package cn.slimsmart.spring.demo.aop;  
 
import org.springframework.stereotype.Service;  
 
@Service  <span style="font-family: Arial, Helvetica, sans-serif;">//使用自动注解的方式实例化并初始化该类</span> 
public class UserServiceImpl implements UserService{  
 
 @Override 
 public String save(String name) {  
        System.out.println("--------save");  
 return "save";  
    }  
 
 @Override 
 public String update(String name) {  
        System.out.println("--------update");  
        System.out.println(1/0);  
 return "update";  
    }  
 
 @Override 
 public String delete(String name) {  
        System.out.println("--------delete");  
 return "delete";  
    }  
 
}  

2.定义切面类

[java]

package cn.slimsmart.spring.demo.aop;  
 
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.After;  
import org.aspectj.lang.annotation.AfterReturning;  
import org.aspectj.lang.annotation.AfterThrowing;  
import org.aspectj.lang.annotation.Around;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Before;  
import org.aspectj.lang.annotation.Pointcut;  
import org.springframework.stereotype.Component;  
 
//@Aspect : 标记为切面类 
//@Pointcut : 指定匹配切点集合 
//@Before : 指定前置通知,value中指定切入点匹配 
//@AfterReturning :后置通知,具有可以指定返回值 
//@AfterThrowing :异常通知 
//@Around 环绕通知 环绕通知的方法中一定要有ProceedingJoinPoint 参数,与Filter中的  doFilter方法类似 
//注意:前置/后置/异常通知的函数都没有返回值,只有环绕通知有返回值 
@Component //使用自动注解的方式实例化并初始化该类 
@Aspect 
public class TestInterceptor {  
 
 //如果要设置多个切点可以使用 || 拼接 
 @Pointcut("execution(* cn.slimsmart.spring.demo.aop.UserServiceImpl.*(..))")  
 private void anyMethod() {  
    }// 定义一个切入点 
 
 @Before(value="anyMethod()")  
 public void doBefore(JoinPoint joinPoint) {  
        System.out.println("前置通知");  
    }  
 
 @AfterReturning(value="anyMethod()",returning="result")  
 public void doAfter(JoinPoint jp, String result) {  
        System.out.println("后置通知");  
    }  
 
 @After("anyMethod()")  
 public void after() {  
        System.out.println("最终通知");  
    }  
 
 @AfterThrowing(value="execution(* cn.slimsmart.spring.demo.aop.*.*(..))",throwing="e")  
 public void doAfterThrow(JoinPoint joinPoint, Throwable e) {  
        System.out.println("异常通知");  
    }  
 
 @Around("execution(* cn.slimsmart.spring.demo.aop.*.*(..))")  
 public Object doBasicProfiling(ProceedingJoinPoint joinPoint) throws Throwable {  
        System.out.println("进入环绕通知");  
        System.out.println("目标类名称:"+joinPoint.getTarget().getClass().getName());  
        System.out.println("方法名称:"+joinPoint.getSignature().getName());  
        System.out.println("方法参数:"+joinPoint.getArgs());  
        System.out.println("staticPart:"+ joinPoint.getStaticPart().toShortString());  
        System.out.println("kind:"+joinPoint.getKind());  
        System.out.println("sourceLocation:"+joinPoint.getSourceLocation());  
        Object object = joinPoint.proceed();// 执行该方法 
        System.out.println("退出方法");  
 return object;  
    }  
 
}  

3.applicationContext.xml配置

[html]

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:context="http://www.springframework.org/schema/context" 
 xmlns:aop="http://www.springframework.org/schema/aop" 
 xmlns:tx="http://www.springframework.org/schema/tx" 
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd  
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> 
 <context:component-scan base-package="cn.slimsmart.spring.demo" /> 
 <!-- 打开aop 注解 --> 
 <aop:aspectj-autoproxy proxy-target-class="true"/> 
 
</beans> 

4.单元测试类

[java]

package cn.slimsmart.spring.demo;  
 
import org.junit.Test;  
import org.junit.runner.RunWith;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.test.context.ContextConfiguration;  
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
 
import cn.slimsmart.spring.demo.aop.UserService;  
 
@RunWith(SpringJUnit4ClassRunner.class)//让junit工作在spring环境中 
@ContextConfiguration(locations={"classpath:applicationContext.xml"})  
public class SpringTest{  
 
 @Autowired 
    UserService userService;  
 
 @Test 
 public void testStart(){  
        System.out.println("启动服务");  
        userService.delete("abc123");  
        System.out.println("====================");  
        userService.update("aaa");  
    }  
 
}  

运行结果:执行update抛异常:/ by zero

[plain]

  1. 启动服务
  2. 进入环绕通知
  3. 目标类名称:cn.slimsmart.spring.demo.aop.UserServiceImpl
  4. 方法名称:delete
  5. 方法参数:[Ljava.lang.Object;@2de1c3f9
  6. staticPart:execution(UserServiceImpl.delete(..))
  7. kind:method-execution
  8. sourceLocation:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@6ed745c2
  9. 前置通知
  10. --------delete
  11. 退出方法
  12. 最终通知
  13. 后置通知
  14. ====================
  15. 进入环绕通知
  16. 目标类名称:cn.slimsmart.spring.demo.aop.UserServiceImpl
  17. 方法名称:update
  18. 方法参数:[Ljava.lang.Object;@1d370b4d
  19. staticPart:execution(UserServiceImpl.update(..))
  20. kind:method-execution
  21. sourceLocation:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@8c6fb37
  22. 前置通知
  23. --------update
  24. 最终通知
  25. 异常通知

注:pom.xml引入的jar包

[html]

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 <groupId>cn.slimsmart.spring.demo</groupId> 
 <artifactId>spring-demo</artifactId> 
 <version>0.0.1-SNAPSHOT</version> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework</groupId> 
 <artifactId>spring-context</artifactId> 
 <version>4.1.4.RELEASE</version> 
 </dependency> 
 <!-- <dependency> --> 
 <!-- <groupId>org.springframework</groupId> --> 
 <!-- <artifactId>spring-tx</artifactId> --> 
 <!-- <version>4.1.4.RELEASE</version> --> 
 <!-- </dependency> --> 
 <!-- <dependency> --> 
 <!-- <groupId>org.springframework</groupId> --> 
 <!-- <artifactId>spring-jdbc</artifactId> --> 
 <!-- <version>4.1.4.RELEASE</version> --> 
 <!-- </dependency> --> 
 <dependency> 
 <groupId>org.springframework</groupId> 
 <artifactId>spring-test</artifactId> 
 <version>4.1.4.RELEASE</version> 
 </dependency> 
 <dependency> 
 <groupId>aspectj</groupId> 
 <artifactId>aspectjrt</artifactId> 
 <version>1.5.4</version> 
 </dependency> 
 <dependency> 
 <groupId>org.aspectj</groupId> 
 <artifactId>aspectjweaver</artifactId> 
 <version>1.8.4</version> 
 </dependency> 
 
 <dependency> 
 <groupId>cglib</groupId> 
 <artifactId>cglib</artifactId> 
 <version>3.1</version> 
 </dependency> 
 <dependency> 
 <groupId>cglib</groupId> 
 <artifactId>cglib-nodep</artifactId> 
 <version>3.1</version> 
 </dependency> 
 <dependency> 
 <groupId>junit</groupId> 
 <artifactId>junit</artifactId> 
 <version>4.12</version> 
 </dependency> 
 
 </dependencies> 
</project> 

若不使用注解的方式,使用schema xml配置(也可以基于spring接口方式实现)的方式,如下参考:

[html]

<aop:config> 
 <aop:aspect id="businessAspect" ref="testInterceptor"> 
 <!-- 配置指定切入的对象 --> 
 <aop:pointcut id="point_cut" expression="execution(* cn.slimsmart.spring.demo.aop.UserServiceImpl.*(..))" /> 
 <!-- 前置通知 --> 
 <aop:before method="doBefore" pointcut-ref="point_cut" /> 
 <!-- 后置通知 returning指定返回参数 --> 
 <aop:after-returning method="doAfter" 
 pointcut-ref="point_cut" returning="result" /> 
 <aop:around method="doAround" pointcut-ref="point_cut"/> 
 <aop:after-throwing method="doThrow" pointcut-ref="point_cut" throwing="e"/> 
 </aop:aspect> 
 </aop:config> 

原文发布于微信公众号 - java达人(drjava)

原文发表时间:2015-06-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一枝花算不算浪漫

[Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

3338
来自专栏cs

spring aop概念以及jdk的动态代理

AOP(Aspect-Oriented Programming),又称为面向切面编程。作为一种编程思想,AOP是 OOP(Object-Oriented Pro...

1034
来自专栏Jed的技术阶梯

Java设计模式之模板方法模式

假设我们现在要造一批悍马汽车,悍马汽车有两个系列H1和H2,首先不考虑任何设计模式,看看设计的类图:

1153
来自专栏Coding迪斯尼

VUE+WebPack游戏设计:实现子弹发射击打外星人效果

993
来自专栏微信公众号:Java团长

Spring AOP的实现原理

AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点...

982
来自专栏一英里广度一英寸深度的学习

Spring 基础

interface声明接口,接口中的函数不用public/private,但是要匹配参数和异常。

941
来自专栏Java帮帮-微信公众号-技术文章全总结

Spring-AOP

AOP引介 AOP(Aspect Oriented Programing)面向切面编程采用横向抽取机制,以取代传统的纵向继承体系的重复性代码(如性能监控/事务管...

3538
来自专栏javathings

Spring 中 AOP 的实现

AOP 称为面向切面编程,在程序开发中,AOP 技术可以在不改变原有方法代码的情况下,把逻辑直接插入到方法上。Spring AOP 的大致原理主要依靠的是动态代...

1074
来自专栏C#

C#操作XML的通用方法总结

    在.net的项目开发中,经常会对XML文件进行操作,由于XML文件可以实现跨平台传输,较多的应用在数据传输中,特总结以下几种常用的XML操作方法: ...

3279
来自专栏xingoo, 一个梦想做发明家的程序员

【Spring实战】—— 13 AspectJ注解切面

前面了解了典型的AOP基于配置的使用方法,下面介绍下如何依赖于注解来实现AOP。 基于注解降低了配置文件的复杂程度,但是引入了程序间的耦合,其中的优劣待用户...

2315

扫码关注云+社区

领取腾讯云代金券