• 概述
  • 准备工作
  • 实例
    • 通过编码的方式使用AspectJ切面
    • 通过配置的方式使用AspectJ切面
      • 自动生成代理的方式
      • 基于Schema的aop命名空间配置的方式

概述

我们之前一个系列的文章,分别使用Pointcut和Advice接口描述切点和增强,并用Advisor整合二者描述切面,@AspectJ则采用注解来描述切点、增强,二者只是表述方式不同,描述内容的本质是完全相同的。


准备工作

  • 在使用@AspectJ之前,必须确保使用的Java5.0以及以上的版本,否则无法使用注解。

  • Spring在处理@AspectJ注解表达式时,需要将Spring的asm模块添加到类路径中。asm是轻量级的字节码处理框架,因为Java的反射机制无法获取入参名,Spring就利用asm处理@AQspectJ中所描述的方法入参名

  • 如果是maven工程,需要在pom.xml添加aspectj.weaver和aspectj.tools类包的依赖。

<!-- asm/cglib依赖(spring依赖) --><dependency><groupId>org.ow2.asm</groupId><artifactId>asm</artifactId><version>${asm.version}</version></dependency><dependency><groupId>org.ow2.asm</groupId><artifactId>asm-util</artifactId><version>${asm.version}</version></dependency><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>${cglib.version}</version><exclusions><exclusion><artifactId>asm</artifactId><groupId>org.ow2.asm</groupId></exclusion></exclusions></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>${aspectj.version}</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>${aspectj.version}</version></dependency><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>${aopalliance.version}</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>${commons-codec.version}</version></dependency>

实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

通过编码的方式使用@AspectJ切面

@AspectJ采用不同的方式对AOP进行描述。

我们依旧采用我们一直使用的服务生的例子

package com.xgj.aop.spring.advisor.aspectJ.aspectJByCode;public class NaiveWaiter implements Waiter {@Overridepublic void greetTo(String name) {System.out.println("NaiveWaiter Greet To " + name);}@Overridepublic void serverTo(String name) {System.out.println("NaiveWaiter Server To " + name);}}

下面使用@AspectJ注解定义一个切面

package com.xgj.aop.spring.advisor.aspectJ.aspectJByCode;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;/*** * * @ClassName: PreGreetingAspect* * @Description: 切面类* * @author: Mr.Yang* * @date: 2017年8月24日 下午3:21:15*/// 通过@Aspect将PreGreetingAspect标注为一个切面
@Aspect
public class PreGreetingAspect {// 定义切点和增强类型@Before("execution(* greetTo(..))")public void beforeGreeting() {// 增强的横切逻辑System.out.println("How are you ?");}
}

从上述代码中,我们可以看到这个切面没有实现任何特殊的接口,它只是一个普通的POJO,特殊之处在于使用了@AspectJ注解。

首先,在PreGreetingAspect类定义出标注了@AspectJ注解,这样,第三方处理程序就可以通过类是否拥有@AspectJ注解来判断其是否是一个切面。

其次,在beforeGreeting()方法处标注了@Before注解,并未改注解提供了成员值“execution(* greetTo(..))”

@Before(“execution(* greetTo(..))”)注解提供了两个信息: @Before注解白该增强是前置增强,而成员值是一个@AspectJ切点表达式。 意思为:在目标类的greetTo方法上织入增强,greetTo()方法可以带带任意的入参和任意的返回值。

最后beforeGreeting()方法是增强说是所使用的横切逻辑,该横切逻辑在目标方法前调用。

我们通过下图来先看下这种关系 《切面的信息构成》

PreGreetingAspect类通过注解和代码,将切点、增强类型和增强的横切逻辑柔和到一个类中,使切面的定义浑然天成。 其实相当于我们之前说的BeforeAdivce、NameMatchMethodPoincut和DefaultPointcutAdvisor三者联合表达的信息。

下面我们通过AspectProxyFactory为NaiverWaiter生成织入PreGreetingAspect切面的代码

package com.xgj.aop.spring.advisor.aspectJ.aspectJByCode;import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;/*** * * @ClassName: PreGreetingAspectTest* * @Description:* * @author: Mr.Yang* * @date: 2017年8月24日 下午3:21:29*/
public class PreGreetingAspectTest {@Testpublic void test() {// 目标类Waiter target = new NaiveWaiter();// 实例化切面代理工厂AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory();// 设置目标对象aspectJProxyFactory.setTarget(target);// 添加切面类aspectJProxyFactory.addAspect(PreGreetingAspect.class);// 生成织入切面的代理对象Waiter proxy = aspectJProxyFactory.getProxy();// 调用业务方法proxy.greetTo("XiaoGongJiang");proxy.serverTo("XiaoGongJiang");}
}

运行结果

How are you ?
NaiveWaiter Greet To XiaoGongJiang
NaiveWaiter Server To XiaoGongJiang

从输出结果,我们可以知道代理对象的greetTo()方法已经被织入了切面类所定义的增强逻辑。


通过配置的方式使用@AspectJ切面

虽然可以通过编程的方式织入切面,但是一般情况下,我们都是通过Spring的配置完成切面织入工作。

自动生成代理的方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 通过配置使用@AspectJ --><!-- 目标Bean -->
<bean id="waiter" class="com.xgj.aop.spring.advisor.aspectJ.aspectJByConf.NaiveWaiter"/>
<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.aspectJByConf.PreGreetingAspect"/>
<!-- 自动代理创建器,自动将@AspectJ注解切面类织入目标Bean中 -->
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/></beans>

测试:

package com.xgj.aop.spring.advisor.aspectJ.aspectJByConf;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** * * @ClassName: PreGreetingAspectTest* * @Description:* * @author: Mr.Yang* * @date: 2017年8月24日 下午3:21:29*/
public class PreGreetingAspectTest {@Testpublic void test() {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/aop/spring/advisor/aspectJ/aspectJByConf/conf-aspectJ.xml");Waiter naiveWaiter = ctx.getBean("waiter", Waiter.class);naiveWaiter.greetTo("XiaoGongJiang");naiveWaiter.serverTo("XiaoGongJiang");}
}

运行结果:

2017-08-24 17:29:48,644  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24177697: startup date [Thu Aug 24 17:29:48 BOT 2017]; root of context hierarchy
2017-08-24 17:29:48,754  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/aspectJByConf/conf-aspectJ.xml]
How are you ?
NaiveWaiter Greet To XiaoGongJiang
NaiveWaiter Server To XiaoGongJiang

基于Schema的aop命名空间配置的方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 使用基于Schema的aop命名空间进行配置 --><!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy/><!-- 目标Bean -->
<bean id="waiter" class="com.xgj.aop.spring.advisor.aspectJ.aspectJByConf.NaiveWaiter"/>
<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.aspectJByConf.PreGreetingAspect"/></beans>

首先在配置文件中引入aop的命名空间;然后通过aop命名空间的<aop:aspectj-atuoproxy/>自动为Spring容器中哪些匹配@AspectJ切面的bean 创建代理,完成切面织入。

当然了,Spring在内部依旧使用AnnotationAspectJAutpProxyCreator进行自动代理的创建工作,但具体的实现细节被<aop:aspectj-atuoproxy/>隐藏起来了。

<aop:aspectj-atuoproxy/>有一个proxy-target-class属性,默认为false,标识使用JDK动态代理技术织入增强。 当配置 <aop:aspectj-autoproxy proxy-target-class="true"/>表示使用CGLib动态代理技术织入增强。

不过即使 proxy-target-class设置为false,如果目标类没有声明接口,Spring将自动使用CGLib动态代理

测试

package com.xgj.aop.spring.advisor.aspectJ.aspectJByConf;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class PreGreetingAspectSchemaTest {@Testpublic void test() {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/aop/spring/advisor/aspectJ/aspectJByConf/conf-aspectJ_schema.xml");Waiter naiveWaiter = ctx.getBean("waiter", Waiter.class);naiveWaiter.greetTo("XiaoGongJiang");naiveWaiter.serverTo("XiaoGongJiang");}
}

运行结果

2017-08-24 17:30:28,141  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24177697: startup date [Thu Aug 24 17:30:28 BOT 2017]; root of context hierarchy
2017-08-24 17:30:28,244  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/aspectJByConf/conf-aspectJ_schema.xml]
How are you ?
NaiveWaiter Greet To XiaoGongJiang
NaiveWaiter Server To XiaoGongJiang

通过输出结果,我们可以看到实现了同样的效果。

Spring-AOP 使用@AspectJ相关推荐

  1. 比较Spring AOP与AspectJ

    本文翻译自博客Comparing Spring AOP and AspectJ 介绍 如今有多个可用的AOP库,这些组件需要回答一系列的问题: 是否与我现有的应用兼容? 我在哪实现AOP? 集成到我的 ...

  2. 比较分析 Spring AOP 和 AspectJ 之间的差别

    面向方面的编程(AOP) 是一种编程范式,旨在通过允许横切关注点的分离,提高模块化.AOP提供方面来将跨越对象关注点模块化.虽然现在可以获得许多AOP框架,但在这里我们要区分的只有两个流行的框架:Sp ...

  3. 在 Spring Boot 中使用 Spring AOP 和 AspectJ 来测量方法的执行时间

    原文链接:https://dzone.com/articles/logging-average-method-execution-times-via-aspectj 作者:Murat Derman 译 ...

  4. aopaspect区别_面试官:什么是AOP?Spring AOP和AspectJ的区别是什么?

    AOP(Aspect Orient Programming),它是面向对象编程的一种补充,主要应用于处理一些具有横切性质的系统级服务,如日志收集.事务管理.安全检查.缓存.对象池管理等. AOP实现的 ...

  5. SpringAop与AspectJ的联系与区别____比较分析 Spring AOP 和 AspectJ 之间的差别

    SpringAop与AspectJ的联系与区别 区别 AspectJ AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Ja ...

  6. 比较Spring AOP和AspectJ

    1. 介绍 当前有多个可用的AOP库,这些库必须能够回答许多问题: 它与我现有的或新的应用程序兼容吗? 在哪里可以实施AOP? 它与我的应用程序集成的速度有多快? 性能开销是多少? 在本文中,我们将着 ...

  7. 框架源码专题:Spring的Aop实现原理,Spring AOP 与 AspectJ 的关系

    文章目录 1. Spring AOP 与 AspectJ 的关系 2. JDK和Cglib动态代理的区别 3. Spring AOP应用案例 4. Spring AOP有几种配置方式? 5. Spri ...

  8. Spring AOP 和 AspectJ的区别

    Spring AOP 和 AspectJ的区别 springAOP 是spring支持的面向切面AOP 编程. AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法 ...

  9. 面试官:说说Spring AOP、AspectJ、CGLIB ?它们有什么关系?

    欢迎关注方志朋的博客,回复"666"获面试宝典 AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务 ...

  10. 面试官:Spring AOP、AspectJ、CGLIB 都是什么鬼?它们有什么关系?

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等. AOP 实现的关键就在 ...

最新文章

  1. 使用jmeter对ActiveMQ集群性能方案进行评估--转载
  2. 【学习笔记】MySQL 数据备份与恢复
  3. 机器学习理论入门:第一章 监督学习与非监督学习介绍
  4. 【数据结构与算法】中缀表达式 - 后缀表达式 - 求值
  5. 这才是真正的蛙泳,还挺能蹦跶......
  6. 如何在生产中检测和诊断慢速代码
  7. jQuery 1.7.1 代码研究 extend
  8. java boolean if_Java if(boolean)和if(boolean=true)区别解析
  9. class触发后让另一个class加样式_Bootstrap的按钮组样式
  10. android源码出现的@字符代表什么意思
  11. 计算机基础知识运算符,计算机基础运算符
  12. Maven:mvn 命令的基本使用
  13. Matlab imfilter函数
  14. SpringBoot请求第三方接口
  15. 2.5 第九讲 一阶微分方程的计算
  16. 微信分享网页链接自定义图片和文字描述
  17. 【银河麒麟】终端安装微信代码
  18. AXURE手机版注册登录原型(下载+教学)
  19. 物联网平台主要提供哪些能力
  20. 计算机考试水平划分,计算机水平等级划分

热门文章

  1. spark从入门到精通spark内存管理详解- 堆内堆外内存管理
  2. tableau可视化数据分析60讲(十四)-tableau可视化视图(交叉表项目符号图)
  3. 探索推荐引擎内部的秘密,第 3 部分: 深入推荐引擎相关算法 - 聚类
  4. matlab reshape使用
  5. java 获取页面元素的位置_Selenium Java 页面元素定位2
  6. 机器学习入门书籍导读-工程高等代数
  7. 你真的懂redis的数据结构了吗?redis内部数据结构和外部数据结构揭秘
  8. Python/WSGI 应用快速入门--转
  9. Tomcat vs. Jetty vs. Undertow: Comparison of Spring Boot Embedded Servlet Containers
  10. nginx大量TIME_WAIT的解决办法--转