Spring除了支持Schema方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明。

6.4.1  启用对@AspectJ的支持

Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:

<aop:aspectj-autoproxy/>  

这样Spring就能发现@AspectJ风格的切面并且将切面应用到目标对象。

6.4.2  声明切面

@AspectJ风格的声明切面非常简单,使用@Aspect注解进行声明:

    @Aspect()
Public class Aspect{
……
}

然后将该切面在配置文件中声明为Bean后,Spring就能自动识别并进行AOP方面的配置:

    <bean id="aspect" class="……Aspect"/>  

该切面就是一个POJO,可以在该切面中进行切入点及通知定义,接着往下看吧。

6.4.3  声明切入点

@AspectJ风格的命名切入点使用org.aspectj.lang.annotation包下的@Pointcut+方法(方法必须是返回void类型)实现。

@Pointcut(value="切入点表达式", argNames = "参数名列表")
public void pointcutName(……) {}

value:指定切入点表达式;

argNames:指定命名切入点方法参数列表参数名字,可以有多个用“,”分隔,这些参数将传递给通知方法同名的参数,同时比如切入点表达式“args(param)”将匹配参数类型为命名切入点方法同名参数指定的参数类型。

pointcutName:切入点名字,可以使用该名字进行引用该切入点表达式。

    @Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {}

定义了一个切入点,名字为“beforePointcut”,该切入点将匹配目标方法的第一个参数类型为通知方法实现中参数名为“param”的参数类型。

6.4.4  声明通知

@AspectJ风格的声明通知也支持5种通知类型:

一、前置通知:使用org.aspectj.lang.annotation 包下的@Before注解声明;

@Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名") 

value:指定切入点表达式或命名切入点;

argNames:与Schema方式配置中的同义。

 

接下来示例一下吧:

1、定义接口和实现,在此我们就使用Schema风格时的定义;

package lqy.springh6_4;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut; 2、定义切面:
@Aspect
public class HelloWorldAspect2 { 3、定义切入点:
@Pointcut(value="execution(* lqy.springh6_2..*.sayBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {} 4、定义通知:
@Before(value = "beforePointcut(param)", argNames = "param")
public void beforeAdvice(String param) {
System.out.println("HelloWorldAspect2:" + param);
} }

xml配置文件中进行如下配置:

<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="helloWorldService" class="lqy.springh6_2.HelloWorldService"/> <bean id="aspect" class="lqy.springh6_4.HelloWorldAspect2"/> </beans>

测试

package lqy.springh6_4;

import lqy.springh6_2.IHelloWorldService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class test2 { /**
* @param args
*/
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("lqy/springh6_4/springh6_4.xml"); IHelloWorldService helloworldService = ctx.getBean("helloWorldService", IHelloWorldService.class);
helloworldService.sayBefore("before"); } }

aaarticlea/png;base64,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" alt="" />

切面、切入点、通知全部使用注解完成:

1)使用@Aspect将POJO声明为切面;

2)使用@Pointcut进行命名切入点声明,同时指定目标方法第一个参数类型必须是java.lang.String,对于其他匹配的方法但参数类型 不一致的将也是不匹配的,通过argNames = "param"指定了将把该匹配的目标方法参数传递给通知同名的参数上;

3)使用@Before进行前置通知声明,其中value用于定义切入点表达式或引用命名切入点;

4)配置文件需要使用<aop:aspectj-autoproxy/>来开启注解风格的@AspectJ支持;

5)需要将切面注册为Bean,如“aspect”Bean;

6)测试代码完全一样。

二、后置返回通知:使用org.aspectj.lang.annotation 包下的@AfterReturning注解声明;

    @AfterReturning(
value="切入点表达式或命名切入点",
pointcut="切入点表达式或命名切入点",
argNames="参数列表参数名",
returning="返回值对应参数名")

value:指定切入点表达式或命名切入点;

pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;

argNames:与Schema方式配置中的同义;

returning:与Schema方式配置中的同义。

@AfterReturning(
value="execution(* cn.javass..*.sayBefore(..))",
pointcut="execution(* cn.javass..*.sayAfterReturning(..))",
argNames="retVal", returning="retVal")
public void afterReturningAdvice(Object retVal) {
System.out.println("===========after returning advice retVal:" + retVal);
}

其中测试代码与Schema方式几乎一样,在此就不演示了

 

三、后置异常通知:使用org.aspectj.lang.annotation 包下的@AfterThrowing注解声明

    @AfterThrowing (
value="切入点表达式或命名切入点",
pointcut="切入点表达式或命名切入点",
argNames="参数列表参数名",
throwing="异常对应参数名")

value:指定切入点表达式或命名切入点;

pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;

argNames:与Schema方式配置中的同义;

throwing:与Schema方式配置中的同义。

@AfterThrowing(
value="execution(* cn.javass..*.sayAfterThrowing(..))",
argNames="exception", throwing="exception")
public void afterThrowingAdvice(Exception exception) {
System.out.println("===========after throwing advice exception:" + exception);
}

其中测试代码与Schema方式几乎一样,在此就不演示了

四、后置最终通知:使用org.aspectj.lang.annotation 包下的@After注解声明;

@After (
value="切入点表达式或命名切入点",
argNames="参数列表参数名")

value:指定切入点表达式或命名切入点;

argNames:与Schema方式配置中的同义;

    @After(value="execution(* cn.javass..*.sayAfterFinally(..))")
public void afterFinallyAdvice() {
System.out.println("===========after finally advice");
}

其中测试代码与Schema方式几乎一样,在此就不演示了

五、环绕通知:使用org.aspectj.lang.annotation 包下的@Around注解声明;

    @Around (
value="切入点表达式或命名切入点",
argNames="参数列表参数名")

value:指定切入点表达式或命名切入点;

argNames:与Schema方式配置中的同义;

@Around(value="execution(* cn.javass..*.sayAround(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("===========around before advice");
Object retVal = pjp.proceed(new Object[] {"replace"});
System.out.println("===========around after advice");
return retVal;
}

其中测试代码与Schema方式几乎一样,在此就不演示了,如果需要请参考AopTest.java中的annotationAroundAdviceTest测试方法。

6.4.5  引入

省略

开涛spring3(6.4) - AOP 之 6.4 基于@AspectJ的AOP的更多相关文章

  1. 利用基于@AspectJ的AOP实现权限控制

    一. AOP与@AspectJ AOP 是 Aspect Oriented Programming 的缩写,意思是面向方面的编程.我们在系统开发中可以提取出很多共性的东西作为一个 Aspect,可以理 ...

  2. Spring 基于 AspectJ 的 AOP 开发

    Spring 基于 AspectJ 的 AOP 开发 在 Spring 的 aop 代理方式中, AspectJ 才是主流. 1. AspectJ 简介 AspectJ 是一个基于 java 语言的 ...

  3. 【AOP】操作相关术语---【Spring】的【AOP】操作(基于aspectj的xml方式)

    [AOP]操作相关术语 Joinpoint(连接点):类里面哪些方法可以被增强,这些方法称为连接点. Pointcut(切入点):在类里面可以有很多的方法被增强,比如实际操作中,只是增强了类里面add ...

  4. 开涛spring3(6.9) - AOP 之 6.9 代理机制

    Spring AOP通过代理模式实现,目前支持两种代理:JDK动态代理.CGLIB代理来创建AOP代理,Spring建议优先使用JDK动态代理. JDK动态代理:使用java.lang.reflect ...

  5. 开涛spring3(6.3) - AOP 之 6.3 基于Schema的AOP

    6.3  基于Schema的AOP 基于Schema的AOP从Spring2.0之后通过“aop”命名空间来定义切面.切入点及声明通知. 在Spring配置文件中,所以AOP相关定义必须放在<a ...

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

    前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...

  7. Spring基于AspectJ的AOP的开发——注解

    源码:https://gitee.com/kszsa/dchart 一, AspectJ的概述: AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法所以它有一个专 ...

  8. Spring框架学习09——基于AspectJ的AOP开发

    1.基于注解开发AspectJ (1)AspectJ注解 基于注解开发AspectJ要比基于XML配置开发AspectJ便捷许多,所以在实际开发中推荐使用注解方式.关于注解的相关内容如下: @Aspe ...

  9. Spring Aop(四)——基于Aspectj注解的Advice介绍

    转发地址:https://www.iteye.com/blog/elim-2395315 4 基于Aspectj注解的Advice介绍 之前介绍过,Advice一共有五种类型,分别是before.af ...

随机推荐

  1. 浅析Java中synchronized与static synchronized

    synchronized关键字 synchronized是进行同步处理而保证线程安全.在一个方法中,如果是方法内的私有变量,那个这个变量是线程安全的,但是类中的实例变量是可能会出现线程安全问题的,当多 ...

  2. Parse error: syntax error, unexpected '[' in D:\phpStudy\WWW\tp5\thinkphp\library\think\Loader.php on line 18

    g刚学习tp5就遇到了这个问题  百思不得其解,看到官网说明 是基于PHP5.4 设计的  打开 phpstudy版本一看 就呵呵呵了 .还是5.3的版本.更换版本之后 就ok了.

  3. 什么是javascript中的静态方法?一个例子让你懂~!

    function Foo(){ this.age = 28};var a = new Foo();alert(a.age);//28alert(a.name);//undifined Foo.name ...

  4. 4 安装MPush

    cnblogs-DOC 1.服务器环境 2.安装Redis3.安装Zookeeper4.安装MPush5.安装Alloc服务6.完整测试7.常见问题 一.Linux安装Mpush [root@loca ...

  5. React+Redux学习笔记:React+Redux简易开发步骤

    前言 React+Redux 分为两部分: UI组件:即React组件,也叫用户自定义UI组件,用于渲染DOM 容器组件:即Redux逻辑,处理数据和业务逻辑,支持所有Redux API,参考之前的文 ...

  6. Asp.net Authorization 学习

    其实使用新的Identity以来一直有一个疑惑,之前的角色管理 在新的Identity中怎么管理的.[AspNetUserClaims] 在新的授权管理中又占什么位置 第一,根据角色授权,刚刚注册的用 ...

  7. 【stm32】时钟树解析

    有时候会突然忘了这个重要的时钟树,这里转载一个比较好的,以防忘记. STM32时钟系统 在STM32中,有五个时钟源,为HSI.HSE.LSI.LSE.PLL. ①HSI是高速内部时钟,RC振荡器,频 ...

  8. 【转载】stm32中断学习

    中断对于开发嵌入式系统来讲的地位绝对是毋庸置疑的,在C51单片机时代,一共只有5个中断,其中2个外部中断,2个定时/计数器中断和一个串口中断,但是在STM32中,中断数量大大增加,而且中断的设置也更加 ...

  9. 【NIO】Java NIO之选择器

    一.前言 前面已经学习了缓冲和通道,接着学习选择器. 二.选择器 2.1 选择器基础 选择器管理一个被注册的通道集合的信息和它们的就绪状态,通道和选择器一起被注册,并且选择器可更新通道的就绪状态,也可 ...

  10. [ext4]空间管理 - 分配机制

     在Ext4系统中,存在很多分配策略,比如预分配.多块分配.延迟分配等   Prealloc预分配 在ext4系统中,对于小文件和大文件的空间申请请求,都有不同的分配策略.对用小文件的空间请求,e ...