AspectJ允许使用注解定义切面、切入点和增强处理,而spring框架则可识别并根据这些注解来生成AOP的代理。spring只是使用了和AspectJ5一样的注解。但并没有使用AspectJ的编译器或织入器(编译时增强.class文件),底层依然使用spring AOP的动态代理。(运行时生成代理增加类,代理类=增强处理+目标对象方法)
一、简单的spring AOP实现实例
前期准备:
将jar包:aspectjweaver.jar、aspectjrt.jar 、aopalliance.jar放入lib目录下
1)、定义普通bean、切面类 。切面类中定义@Before的增强处理
包路径:com.spring.aspect.log.LogAspect.java
@Aspect
public class LogAspect {
//将com.spring.test1包下的所有类的所有方法,织入Before增强通知
@Before("execution(* com.spring.test1.*.*(..))")
public void log(){
System.out.println("打日志");
}
}
com.spring.test1下有以下两个bean:Person、Axe,这两个bean将被织入前置通知
@Component
public class Person {
@Autowired
public Axe axe;
public void printAxe(){
System.out.println(axe.chop());
}
}
@Component
public class Axe {
public String chop(){
return "这是axe方法";
}
}
2)、 在spring配置文件中,spring-config.xml下增加如下配置:
<!-- 扫描bean组件 -->
<context:annotation-config />
<!-- 启动@AspectJ支持 -->
<aop:aspectj-autoproxy/>
<!-- 添加bean组件、切面的扫描包 -->
<context:component-scan base-package="com.spring.test1,com.spring.aspect.log">
<context:include-filter type="annotation"
expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
执行main方法:
public class GetSpringBeanByxml {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
Person person =ctx.getBean("person",Person.class);
person.printAxe();
}
}
运行结果如下:
打日志
打日志
这是axe方法
-------------------------------------------------------------------------------------------------------------------------
二、定义切入点
定义切入点实质就是为切入点起一个名称。可以在多个增强处理方法上重复使用该名称。
切入点采用一个普遍的方法(方法体通常为空)来定义,切入点方法的返回值必须为void,并且用@PointCut来注释。如下:(修改一 中的logAspect()方法)
@Aspect
public class LogAspect {
//定义切入点
@PointCut("execution(* com.spring.test1.*.*(..))")
public void addLog(){}
//使用切入点
@Before(pointcut="addLog()")
public void log(){
System.out.println("打日志");
}
}
一旦程序定义了切入点后,程序就可以重复使用该切入点,甚至可以在其它切面类、其它包的切面类中使用该切入点,至于能否在其它切面类、其它包切面类中使用该切入点,取决于改切入点方法前的访问控制符。例如上面addlog()方法的访问控制符为public,则意味可以在任何其它切面类中访问该切入点,如果为private,则只能在改切面中使用该切入点。
在其它切面类中使用该切入点方法如下:
@Aspect
public class TransAspect {
//使用切入点
@Before(pointcut="LogAspect.addLog()")
public void log(){
System.out.println("打日志");
}
}
-----------------------------------------------------------------------------------------------------------------------------
三、AOP增强处理注解:
@After("execution(* org......*.*(..))") 增强处理不管目标方法如何结束(包括正常结束和异常结束)都织入
@AfterReturning(returning="rvt“, "execution(* org......*.*(..))")只有目标方法正常结束才被织入 returning是只目标方法的返回类型。rvt为object,只有目标方法为object类型,才会被织入。Object rvt可做于增强处理方法的形参。来获取目标方法的返回值。
@AfterThrowing(throwing="ex" ,"execution(* org......*.*(..))")处理目前方法抛异常的情况。throwing=NullPointer-Exception,则只处理nullPointException异常的方法
@Around
@Around可以决定目标方法什么时候执行,如何执行,甚至阻止目标方法的执行。改变目标方法的返回值。但通常需要在线程安全的情况下使用。@Around增强处理方法的第一个形参必须是ProceedingJoinPoint类型,调用ProceedingJoinPoint的proceed()方法,目标方法才会被执行,否则目标方法不会被执行。proceed()方法有一个参数object[]数组,该数组的值被传入目标方法作为目标方法的实参。
例:
@Aspect
public class TxAspect{
@Around("execution(* com.spring.test1.*.*(..))")
public Object processTx(ProceedingJoinPoint jp){
System.out.println("执行目标方法开始之前,模拟开始事务。。。。”)
//获取目标方法的原始参数
Object[] args=jp.getArgs();
if(args!=null &&args.length>1){
//修改目标参数第一参数的值
arg[0] = “增强的前缀”+arg[0];
}
//以改变后的参数取执行目标方法,并保存目标方法的返回值
Object rvt = jp.proceed(args);
System.out.println("执行目标方法开始之前,模拟结束事务。。。。”)
if(rvt != null && rvt instanceOf Integer)
rvt = (Integer)rvt* (Integer)rvt;
return rvt;
}
------------------------------------------------------
四、访问目标方法的参数:
修改如下方法,使其访问目标方法的参数:
@Aspect
public class LogAspect {
@Before("execution(* com.spring.test1.*.*(..))")
public void log(){
System.out.println("打日志");
}
}
第一种方式:修改为:
@Aspect
public class LogAspect {
@Before("execution(* com.spring.test1.*.*(..))")
public void log(JoinPoint jp){
System.out.println("打日志");
System.out.println(“被织入增强处理的目标方法为:” + jp.getSignature().getName());
System.out.println(“被织入增强处理的目标方法参数为:” + jp.getArgs());
}
}
第二种方式,修改为:
@Aspect
public class LogAspect {
@Before("execution(* com.spring.test1.*.*(..)) && args(arg0,arg1)")
public void log(String arg0,String arg1){
System.out.println("打日志");
System.out.println(“目标方法第一个参数为:” + arg0);
System.out.println(“目标方法第二个参数为:” + arg1);
}
}
第二种方式,在切入点加&& args(arg0,arg1)部分,意味可以在增强处理方法中指定两个形参,定义这两个形参时,类型可以随意指定,一旦指定了类型,则会限制目标方法。例如此处指定了两个string类型的参数,这就意味着目前方法必须带有两个string类型的参数。
--------------------------------------
五、增强处理的织入顺序
在不同的切面里两个增强处理需要在同一连接点被织入时,spring AOP将随机的顺序来织入这两个增强处理。如果指定不同切面的增强处理的优先级,有如下两种方式:
1)让切面类实现org.springframework.core.Ordered接口。实现改接口的intgetOrder()方法。改方法返回值越小优先级越高。
2)直接使用@Order注解来修改切面类。使用@order注解时指定一个int型的value属性。改属性值越小,优先级越高。
相关推荐
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
本篇文章将深入探讨如何在Spring中通过注解实现AOP。 首先,了解AOP的基本概念。面向切面编程是一种编程范式,它允许程序员定义“切面”,这些切面包含了跨越多个对象的行为或责任。切点是这些行为插入到主业务逻辑...
在这个基于配置文件的实现中,我们首先需要在Spring配置文件(如applicationContext.xml)中定义一个切面。切面通常由一个或多个通知组成,我们可以使用`<aop:config>`标签来声明切面。例如: ```xml <aop:config> ...
**Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...
5. **@EnableAspectJAutoProxy**: 在Spring配置类上添加此注解,启用基于Java代理的AOP支持,这样Spring会自动检测并处理带有@Aspect注解的类。 ```java @Configuration @EnableAspectJAutoProxy public class ...
2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑实现 (需要知道原理的请看spring aop源码,此处不做赘述) 3、可在现有源码上快速进行功能扩展 4、spring boot,mybatis,druid,spring aop的使用
在这个场景中,我们将使用Spring AOP来实现一个日志记录的功能,以追踪系统中各个方法的调用情况,包括访问时间以及传递的参数。下面将详细阐述如何实现这一目标。 首先,我们需要了解AOP的基本概念。AOP的核心是切...
在Spring AOP中,我们通常使用@Aspect注解来定义切面类。切面类中可以包含多个通知(Advice),包括前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知...
在Spring框架中,基于注解的AOP(面向切面编程)是一种强大的工具,它允许开发者无需编写XML配置即可实现切面。这种编程方式极大地提高了代码的可读性和可维护性。下面我们将深入探讨如何使用注解来实现Spring AOP。...
这个"spring aop jar 包"包含了实现这一功能所需的类和接口,使得开发者能够轻松地实现面向切面的编程。 在Spring AOP中,主要涉及以下几个核心概念: 1. **切面(Aspect)**:切面是关注点的模块化,比如日志记录...
2. **基于注解的AOP**:Spring 2.5开始支持注解驱动的AOP,通过在方法上使用`@Before`、`@After`、`@AfterReturning`、`@AfterThrowing`、`@Around`等注解来定义通知。 3. **基于XML配置的AOP**:在Spring的配置...
XML配置是Spring AOP早期的主要实现方式,虽然现在有更简洁的注解式配置,但理解XML配置方式对于深入理解AOP原理仍然很有帮助。下面我们将详细探讨如何通过XML配置实现Spring AOP。 首先,我们需要在Spring配置文件...
Spring AOP在内部也是基于类似的方式工作,但它的实现更为复杂和高效。它不仅可以处理接口代理,还可以处理基于类的代理,支持CGLIB库生成字节码实现。此外,Spring AOP还提供了一套强大的切点表达式和注解,使得...
Spring支持两种AOP的实现方式:Spring AspectJ注解风格和Spring XML配置风格。使用AspectJ注解风格是最常见的,它允许开发者直接在方法上使用注解来定义切面。 Spring AOP中有五种不同类型的的通知(Advice): 1....
总结一下,通过上述步骤,我们已经在Spring Boot应用中利用Spring AOP和注解方式实现了数据脱敏。这个拦截器可以在不修改原有业务代码的情况下,确保敏感信息在响应给客户端之前得到处理,提高了应用的安全性。同时...
1. 注解驱动的AOP:这是最常用的实现方式,通过在方法上添加注解(如`@Before`, `@After`, `@Around`, `@AfterReturning`, `@AfterThrowing`)来定义通知,并使用`@Aspect`注解定义切面。 2. XML配置驱动的AOP:...
在Spring框架中,AOP的实现有两种主要方式:一种是基于XML配置,另一种是基于注解。本篇将主要讨论如何通过注解方式来实现AOP编程。 首先,我们需要了解Spring中的核心注解。`@Aspect`是定义一个切面的注解,通常会...
Spring AOP就是基于这些接口进行设计的,因此这个库是Spring AOP和其他AOP实现之间协作的基础。 在实际使用中,我们需要在项目的类路径下包含这些Jar包,并在Spring配置文件中启用AOP支持。例如,可以通过以下XML...
在本主题中,我们将深入探讨Spring AOP的注解版,它是基于Java注解的实现,简化了配置并提高了代码的可读性。 首先,让我们理解AOP的基本概念。AOP是一种编程范式,允许程序员定义“切面”,这些切面封装了跨越多个...
总结,这个"SpringAOP简单项目实现"涵盖了Spring AOP的基础知识,包括切面、通知、切入点的定义与配置,以及如何在实际项目中使用Maven进行构建和依赖管理。对于初学者来说,这是一个很好的实践案例,能够帮助他们...