用 AspectJ 注解声明切面:

  • 要在 Spring 中声明 AspectJ 切面 , 只需要在 IOC 容器中将切面声明为 bean 实例。当在 Spring IOC 容器中初始化 AsjectJ 切面之后 , Spring IOC 容器就会为那些与 AspectJ 切面相匹配的 bean 创建代理。
  • 在 ApectJ 注解中 , 切面只是一个带有 @Asject 注解的 Java 类。
  • 通知是标注有某种注解的简单的 Java 方法。
  • AspectJ 支持 5 种类型的通知注解:
    1. @Before:前置通知 , 在方法执行之前执行。
    2. @After:后置通知 , 在方法执行之后执行。
    3. @AfterReturning:返回通知 , 在方法返回结果之后执行。
    4. @AfterThrowing:异常通知 , 在方法抛出异常之后。
    5. @Around:环绕通知 , 围绕着方法执行。

前置通知:

 <?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- IOC 扫描包 -->
<context:component-scan base-package="com.itdoc.spring.aop.impl"></context:component-scan>
<!-- 使 AspectJ 注解起作用, 自动为匹配的类生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>

注意:一定要添加 aop 命名空间。

 package com.itdoc.spring.aop.impl;

 import org.springframework.stereotype.Component;

 /**
* http://www.cnblogs.com/goodcheap
*
* @author: Wáng Chéng Dá
* @create: 2017-03-03 19:34
*/
@Component
public interface Arithmetic { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); }
 package com.itdoc.spring.aop.impl;

 import org.springframework.stereotype.Component;

 /**
* http://www.cnblogs.com/goodcheap
*
* @author: Wáng Chéng Dá
* @create: 2017-03-03 19:35
*/
@Component("arithmetic")
public class ArithmeticImpl implements Arithmetic {
@Override
public int add(int i, int j) {
int result = i + j;
return result;
} @Override
public int sub(int i, int j) {
int result = i - j;
return result;
} @Override
public int mul(int i, int j) {
int result = i * j;
return result;
} @Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
 package com.itdoc.spring.aop.impl;

 import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; import java.util.Arrays; /**
* http://www.cnblogs.com/goodcheap
* 声明为一个切面的类: 需要把该类放到 IOC 容器中, 再声明为一个切面。
* @author: Wáng Chéng Dá
* @create: 2017-03-03 21:37
*/
@Aspect
@Component
public class LoggingAspect { //声明该方法为前置通知: 在目标方法执行之前开始执行。
@Before("execution(* com.itdoc.spring.aop.impl.*.*(..))")
public void beforeMethod(JoinPoint joinPoint) {
Object methodName = joinPoint.getSignature().getName();
Object args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " begins with " + args);
}
}

@Before("execution(* com.itdoc.spring.aop.impl.*.*(..))")

  • 第一颗 * :代表任意修饰符 , 任意返回值。
  • 第二颗 * :代表任意对象。
  • 第三颗 * :代表任意方法。
  • 最后的 .. :代表任意参数。

注意:在 AspectJ 中 , 切点表达式可以通过操作符 && , || , ! 结合起来。

 package com.itdoc.spring.aop.impl;

 import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* http://www.cnblogs.com/goodcheap
*
* @author: Wáng Chéng Dá
* @create: 2017-03-03 21:32
*/
public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Arithmetic arithmetic = (Arithmetic) ctx.getBean("arithmetic");
System.out.println("result = " + arithmetic.add(9, 5));
System.out.println("result = " + arithmetic.sub(9, 5));
}
}

控制台输出:

The method add begins with [9, 5]
result = 14
The method sub begins with [9, 5]
result = 4

后置通知:

  • 后置通知是在连接点完成之后执行的 , 即连接点返回结果或者抛出异常的时候。
  • 一个切面可以包括一个或者多个通知。
 package com.itdoc.spring.aop.impl;

 import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; import java.util.Arrays; /**
* http://www.cnblogs.com/goodcheap
* 声明为一个切面的类: 需要把该类放到 IOC 容器中, 再声明为一个切面。
* @author: Wáng Chéng Dá
* @create: 2017-03-03 21:37
*/
@Aspect
@Component
public class LoggingAspect { //声明该方法为前置通知: 在目标方法执行之前开始执行。
@Before("execution(* com.itdoc.spring.aop.impl.*.*(..))")
public void beforeMethod(JoinPoint joinPoint) {
Object methodName = joinPoint.getSignature().getName();
Object args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " begins with " + args);
} //声明该方法为后置通知: 在目标方法执行之后(无论是否发生异常)开始执行。
@After("execution(* com.itdoc.spring.aop.impl.*.*(..))")
public void afterMethod(JoinPoint joinPoint) {
Object methodName = joinPoint.getSignature().getName();
Object args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " ends with " + args);
}
}
 package com.itdoc.spring.aop.impl;

 import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* http://www.cnblogs.com/goodcheap
*
* @author: Wáng Chéng Dá
* @create: 2017-03-03 21:32
*/
public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Arithmetic arithmetic = (Arithmetic) ctx.getBean("arithmetic");
System.out.println("result = " + arithmetic.add(9, 5));
System.out.println("result = " + arithmetic.div(9, 0));
}
}

控制台输出:

Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.itdoc.spring.aop.impl.ArithmeticImpl.div(ArithmeticImpl.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:43)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy8.div(Unknown Source)
at com.itdoc.spring.aop.impl.Main.main(Main.java:19)
The method add begins with [9, 5]
The method add ends with [9, 5]
result = 14
The method div begins with [9, 0]
The method div ends with [9, 0]

返回通知:

无论连接点是正常返回还是抛出异常 , 后置通知都会执行。如果只想在连接点返回的时候记录日志 , 应使用返回通知代替后置通知。

 package com.itdoc.spring.aop.circular;

 import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; /**
* 通知
* http://www.cnblogs.com/goodcheap
*
* @author: Wáng Chéng Dá
* @create: 2017-03-04 9:50
*/
@Aspect
@Component
public class AsjectLogging { /**
* 在方法正常结束后执行代码。
* 返回通知是可以访问到方法的返回值的。
*/
@AfterReturning(value = "execution(* com.itdoc.spring.aop.circular.*.*(..))", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
Object methodName = joinPoint.getSignature().getName();
System.out.println("The method " + methodName + " ends with " + result);
}
}

异常通知:

 package com.itdoc.spring.aop.circular;

 import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; /**
* 通知
* http://www.cnblogs.com/goodcheap
*
* @author: Wáng Chéng Dá
* @create: 2017-03-04 9:50
*/
@Aspect
@Component
public class AsjectLogging { /**
* 在目标方法出现异常时候执行的代码。
* 可以访问到异常对象, 且可以指定在出现特定异常时再执行的代码。
*/
@AfterThrowing(value = "execution(* com.itdoc.spring.aop.circular.*.*(..))", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Exception e) {
Object methodName = joinPoint.getSignature().getName();
System.out.println("The method " + methodName + " exception with " + e);
}
}

环绕通知:

 package com.itdoc.spring.aop.circular;

 import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; import java.util.Arrays; /**
* 通知
* http://www.cnblogs.com/goodcheap
*
* @author: Wáng Chéng Dá
* @create: 2017-03-04 9:50
*/
@Aspect
@Component
public class AsjectLogging { /**
* 环绕通知需携带 ProceedingJoinPoint 类型的参数。
* 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型参数可以决定是否执行目标方法。
* 环绕通知必须有返回值, 返回值即目标方法的返回值。
*
* @param point
* @return
*/
@Around("execution(* com.itdoc.spring.aop.circular.*.*(..))")
public Object around(ProceedingJoinPoint point) {
Object methodName = point.getSignature().getName();
Object[] args = point.getArgs();
Object result = null;
try {
//前置通知
System.out.println("The method " + methodName + " begins with" + Arrays.asList(args));
//执行方法
result = point.proceed();
//返回通知
System.out.println("The method " + methodName + " ends with " + result);
} catch (Throwable e) {
e.printStackTrace();
//异常通知
System.out.println("The method " + methodName + " exception with " + e);
} finally {
//后置通知
System.out.println("The method " + methodName + " ends");
}
return result;
}
}

Spring学习--用 ASpectJ 注解实现 AOP的更多相关文章

  1. spring学习笔记二 注解及AOP

    本节需要导入spring-aop包 注解 使用注解的目的是为了代替配置,在使用注解时,省略键时,则是为value赋值. 扫描某个包下的所有类中的注解 <?xml version="1. ...

  2. Spring学习之Aspectj开发实现AOP

    Aspectj是一个基于Java语言的Aop框架,它提供了强大的Aop功能. Aspectj简介: 1.Aspectj是一个面向切面的框架,它扩展了Java语言,它定义了一个Aop语法. 2.所以它有 ...

  3. Spring学习笔记5——注解方式AOP

    第一步:注解配置业务类 使用@Component("Pservice")注解ProductService 类 package com.spring.service; import ...

  4. spring 学习(三):aop 学习

    spring 学习(三):aop 学习 aop 概念 1 aop:面向切面(方面)编程,扩展功能不修改源代码实现 2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 3 aop底层使用动态代 ...

  5. spring-AOP框架(基于AspectJ注解配置AOP)

    基于AspectJ注解配置AOP 1.加入jar包: 要在Spring应用中使用AspectJ注解,必须在classpath下包含AspectJ类库:aopalliance.jar.aspectj.w ...

  6. Spring学习4-面向切面(AOP)之Spring接口方式

    一.初识AOP    关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节       1.AOP:Aspect ...

  7. Spring学习_day02_AOP,AspectJ,JdbcTemplate

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! Spring_day02 一.AOP面向切面编程 1. ...

  8. Spring学习笔记(12)——aop

    先了解AOP的相关术语:1.通知(Advice):通知定义了切面是什么以及何时使用.描述了切面要完成的工作和何时需要执行这个工作.2.连接点(Joinpoint):程序能够应用通知的一个"时 ...

  9. Spring学习笔记-面向切面(AOP)-04

    什么是面向切面编程 先大概了解一下部分术语 横切关注点:软件开发中,散布于多出的功能称为横切关注点(cross-cutting concern),简单的可以描述为可以影响应用多处的功能,比如日志.安全 ...

随机推荐

  1. kafka重置offset

    kafka重置offset   1.删除zookeeper上节点信息 打开client :./zkCli.sh -server 127.0.0.1:12181 删除consumer:rmr /cons ...

  2. C# List集合去重操作注意点

    今天调试代码时发现list的distinct方法在对引用类型操作时并没有去重,后来查阅资料发现list去重操作对象集合时比较的是对象的一个个引用地址, 因为集合里的对象都是一个个单独的实例,所以并不会 ...

  3. golang获取调用者的方法名及所在源码行数

    package main import "runtime" import "log" func main() { test() } func test() { ...

  4. VM打开虚拟机文件报错

    用VM打开以前的虚拟机文件报错 Cannot open the disk 'F:/****.vmdk' or one of the snapshot disks it depends on. 这种问题 ...

  5. 步骤2:JMeter 分布式测试(性能测试大并发、远程启动解决方案)

    转载(记录) http://www.cnblogs.com/fengpingfan/p/5583954.html http://www.cnblogs.com/puresoul/p/4844539.h ...

  6. 初探 Qt Opengl【2】

    最近在研究QOPengl QGraphicsView QGraphicsItemQGraphicsScene不过也只是皮毛,也不是做什么技术贴,就是记录一下自己在其中遇到的问题,和自己新学到的东西. ...

  7. jmeter接口测试--响应结果Unicode转码成中文

    jmeter接口测试-响应结果Unicode转码成中文 一般情况下,接口返回数据都会经过加密,所以有时相应结果会显示为Unicode,因此,需添加BeanShell PostProcessor,加入代 ...

  8. AcCoder Contest-115 D - Christmas

    D - Christmas Time limit : 2sec / Memory limit : 1024MB Score : 400 points Problem Statement In some ...

  9. struts2中的action为什么要继承ActionSupport类,不继承也可以,有什么好处?

    简单来说,有很多相关的方法都加载进来,你直接调用就行了,而且在安全上和稳定性上做了很好的处理 实际上继承ActionSupport之后 就等同于实现了很多接口 Action,Validateable, ...

  10. BZOJ 4029 HEOI2015 定价 数位贪心

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4029 题意概述:对于一个数字的荒谬程度定义如下:删除其所有的后缀0,然后得到的数字长度为a ...