Spring-AOP 使用@AspectJ
来源:互联网 发布:手机照片阅读软件 编辑:程序博客网 时间:2024/06/03 17:26
- 概述
- 准备工作
- 实例
- 通过编码的方式使用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 { @Override public void greetTo(String name) { System.out.println("NaiveWaiter Greet To " + name); } @Override public 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标注为一个切面@Aspectpublic 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 { @Test public 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 XiaoGongJiangNaiveWaiter 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 { @Test public 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 hierarchy2017-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 XiaoGongJiangNaiveWaiter 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.xsd http://www.springframework.org/schema/aop http://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 { @Test public 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 hierarchy2017-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 XiaoGongJiangNaiveWaiter Server To XiaoGongJiang
通过输出结果,我们可以看到实现了同样的效果。
- Spring-AOP 使用@AspectJ
- Spring AOP使用ASPECTJ错误
- Spring aop之使用AspectJ
- 使用Spring AOP 的@AspectJ记录日志
- spring 学习笔记 使用aspectj开发aop
- 使用Spring AOP和AspectJ编排工作流
- Spring AOP使用@AspectJ实现日志管理
- Spring中使用AspectJ实现AOP
- Spring-AOP切面+Aspectj框架的使用
- spring学习之使用AspectJ实现AOP
- Spring Boot AspectJ AOP的使用
- spring之基于aspectj注解aop使用
- Spring 之AOP 使用@AspectJ注解方式
- 【Spring AOP】基于AspectJ的AOP基本使用
- Spring AOP + AspectJ framework
- Spring AOP与Aspectj
- spring AspectJ aop学习
- spring aop AspectJ
- KHL 006 作品-计算机-KM-小试-博客系统-功能记录
- 学习日记-world添加分割线
- KHL 007 转身-本科-编译原理
- 全面分析Spring的编程式事务及声明式事务管理
- 图像算法工程师招聘要求
- Spring-AOP 使用@AspectJ
- Effective STL学习笔记-条款1
- Effective STL学习笔记-条款7
- Effective STL学习笔记-条款8-9
- 8皇后 n皇后 非递归
- Hive 小文件问题的处理
- log4j配置
- 深入理解 Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
- node.JS问题集锦