[Spring实战系列](18)注解切面

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/50659876 使用注解来创建切面是AspectJ 5所引入的关键特性。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/50659876
使用注解来创建切面是AspectJ 5所引入的关键特性。在AspectJ 5之前,编写AspectJ切面需要学习一种Java语言的扩展,但是AspectJ面向注解的模型可以非常简单的通过少量注解把任意类转变为切面。

回顾一下Audience类,没有任何地方让它成为一个切面,我们不得不使用XML声明通知和切点。

我们通过@AspectJ注解,我们再看看Audience类,不需要任何额外的类或Bean声明就能将它转换为一个切面。

 
   
package com.sjf.bean;
/**
* 歌手实体类
* @author sjf0115
*
*/
public class Singer {
 
public void perform() {
System.out.println("正在上演个人演唱会... ");
}
}

 
   
package com.sjf.bean;
 
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
 
/**
* 观众实体类(注解为切面)
* @author sjf0115
*
*/
@Aspect
public class Audience {
// 定义切点
@Pointcut("execution(* com.sjf.bean.Singer.perform(..))")
public void SingerPerform(){
// 空方法
}
// 表演之前
@Before("SingerPerform()")
public void takeSeats(){
System.out.println("the audience is taking their seats...");
}
// 表演成功之后
@AfterReturning("SingerPerform()")
public void applaud(){
System.out.println("very good, clap clap clap...");
}
// 表演失败之后
@AfterThrowing("SingerPerform()")
public void demandRefund(){
System.out.println("very bad, We want our money back...");
}
}
新的Audience类现在已经使用@AspectJ注解进行标注。该注解标示了Audience不仅仅是一个POJO,还是一个切面。

@Pointcut注解用于定义一个可以在@AspectJ切面内可重用的切点@Pointcut注解的值是一个AspectJ切点表达式(这里标示切点必须匹配Singer的perform()方法)。 切点的名称来源于注解所应用的方法名称。因为,该切点的名称为SingerPerform()。SingerPerform()方法的实际内容并不重要,它只是一个标示,供@Pointcut注解依附。

Audience的每一个方法都是用通知注解来标注。takeSeats()方法 使用@Before注解来标示它们是前置通知方法。applaud()方法 使用@AfterReturning注解来标示它是后置通知方法。demandRefund()方法使用 @AfterThrowing注解标示它在抛出异常时该方法被会调用。SingerPerform()切点的名称作为参数的值赋予给所有的通知注解,来标示每一个通知方法应该应用在哪。

注意:

除了注解和无操作的SingerPerform()方法,Audience类在实现上并没有任何改变,Audience类仍然是一个简单的Java对象,能够像以前一样使用(在Spring中使用Bean进行配置)。

因为Audience类本身包含了所有它所需要定义的切点和通知,所以我们不在需要在XML配置中声明切点和通知。为了让Spring将Audience应用为一个切面,我们需要 在Spring上下文中声明一个自动代理Bean该Bean知道如何把@AspectJ注解所标注的Bean转变为代理通知

为此,Spring自带了名为 AnnotationAwareAspectJProxyCreator的自动代理创建类。我们可以在Spring上下文中把 AnnotationAwareAspectJProxyCreator注册为一个Bean,但是这个类文字太长,不宜使用。因此,我们使用Spring的aop空间提供的一个自定义配置元素( <aop:aspectj-autoproxy/> 来代替前者,这个更易使用。
 
   
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id = "singer" class = "com.sjf.bean.Singer">
</bean>
<bean id = "audience" class = "com.sjf.bean.Audience">
</bean>
<aop:aspectj-autoproxy/>
</beans>
<aop:aspectj-autoproxy/>配置元素将在Spring上下文中创建一个 AnnotationAwareAspectJProxyCreator类,它会自动代理一些Bean,这些Bean的方法需要与使用@AspectJ注解的Bean中所定义的切点相匹配。

运行结果:

the audience is taking their seats...
正在上演个人演唱会... 
very good, clap clap clap...  

注意:

<aop:aspect>元素和@AspectJ注解都是把一个POJO转变为一个切面的有效方式。但是<aop:aspect>相对@AspectJ的一个明显优势是:不需要实现切面功能的代码(本例中是Audience类代码)。通过@AspectJ,我们必须标注类和方法,它需要有源码

1. 注解环绕通知

像Spring基于XML的AOP一样,@AspectJ注解的使用不仅仅限于定义前置和后置通知类型。我们还可以创建环绕通知。
 
   
@Around("SingerPerform()")
public void PerformTime(ProceedingJoinPoint joinPoint){
// 演出之前
System.out.println("the audience is taking their seats...");
try {
long start = System.currentTimeMillis();
// 执行演出操作
joinPoint.proceed();
long end = System.currentTimeMillis();
// 演出成功
System.out.println("very good, clap clap clap...");
System.out.println("该演出共需要 "+(end - start) + " milliseconds");
} catch (Throwable e) {
// 演出失败
System.out.println("very bad, We want our money back...");
e.printStackTrace();
}
}
在这里,@Around注解标示了PerformTime()方法将被作为环绕通知应用与SingerPerform()切点。和之前使用XML方式唯一的区别就是用@Around注解所标注的。简单的使用@Around注解来标注方法并不足以调用proceed()方法,因此,被环绕通知的方法必须接受一个ProceedingJoinPoint对象作为方法入参,并在对象上调用proceed()方法。

2. 传递参数给所标注的通知

之前我们曾经使用Spring基于XML的切面声明为通知传递参数,而是@AspectJ注解为通知传递参数,与之相比并没有太大的区别。
 
   
package com.sjf.bean;
/**
* 歌手实体类
* @author sjf0115
*
*/
public class Singer {
 
public void perform(String song) {
System.out.println("正在上演个人演唱会... " + song);
}
}

 
   
package com.sjf.bean;
 
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
 
/**
* 主办方实体类
* @author sjf0115
*
*/
@Aspect
public class Organizers {
// 定义切点
@Pointcut("execution(* com.sjf.bean.Singer.perform(String)) and args(song)")
public void SingerPerform(){
//
}
// 表演之前
@Before("SingerPerform() and args(song)")
public void BeforeSong(String song){
System.out.println("演唱会马上就开始了,演唱歌曲为 " + song);
}
}
<aop:pointcut>元素变为@Pointcut注解,<aop:before>元素变为@Before注解。


不知道下面配置出现报错如何解决?求解.....
 
   
// 定义切点
@Pointcut("execution(* com.sjf.bean.Singer.perform(String)) and args(song)")
public void SingerPerform(String song){
//
}
// 表演之前
@Before("SingerPerform(song)")
public void BeforeSong(String song){
System.out.println("演唱会马上就开始了,演唱歌曲为 " + song);
}


来源于:《Spring实战》



目录
相关文章
|
7月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
1073 128
|
6月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
1131 2
Spring Boot 3.x 微服务架构实战指南
|
6月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
6月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
672 2
|
7月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
484 12
|
7月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
371 0
探索Spring Boot的@Conditional注解的上下文配置
|
7月前
|
智能设计 Java 测试技术
Spring中最大化@Lazy注解,实现资源高效利用
本文深入探讨了 Spring 框架中的 `@Lazy` 注解,介绍了其在资源管理和性能优化中的作用。通过延迟初始化 Bean,`@Lazy` 可显著提升应用启动速度,合理利用系统资源,并增强对 Bean 生命周期的控制。文章还分析了 `@Lazy` 的工作机制、使用场景、最佳实践以及常见陷阱与解决方案,帮助开发者更高效地构建可扩展、高性能的 Spring 应用程序。
293 0
Spring中最大化@Lazy注解,实现资源高效利用
|
存储 XML 缓存
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache功能的开发实战指南(一)
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache功能的开发实战指南
1176 0
|
监控 Java 应用服务中间件
Spring Cloud & Alibaba 实战 | 第十二篇: 微服务整合Sentinel的流控、熔断降级,赋能拥有降级功能的Feign新技能熔断,实现熔断降级双剑合璧(一))(JMeter模拟测试)
Spring Cloud & Alibaba 实战 | 第十二篇: 微服务整合Sentinel的流控、熔断降级,赋能拥有降级功能的Feign新技能熔断,实现熔断降级双剑合璧(JMeter模拟测试)(一)

热门文章

最新文章