一、AspectJ概述

AspectJ是一个面向切面的框架,它扩展了Java语言、定义了AOP语法,能够在编译期提供代码的织入,它提供了一个专门的编译期用来生成遵守字节编码规范的Class文件。

@Aspect是AspectJ 5新增的功能,使用JDK 5.0注解技术和正规的AspectJ切点表达式语言描述切面。因此在使用@Aspect之前,需要保证所使用的JDK是5.0或更高版本,否则将无法使用注解技术。

Spring通过集成AspectJ实现了以注解的方式定义切面,大大减轻了配置文件的工作量。此外,因为Java的反射机制无法获取方法参数名,Spring还需要利用轻量级的字节码处理框架asm(已集成在Spring Core模块中)处理@AspectJ中所描述的方法参数名。

二、@Aspect(定义切面)、@Before(前置增强)、@AfterReturning(后置增强)注解配置切面

1、使用注解定义切面以实现日志切面功能,如下

package edu.cn.service;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.util.Arrays; @Aspect
public class UserServiceLogger {
private static final Logger log = LoggerFactory.getLogger(UserServiceLogger.class); @Before("execution(* edu.cn.service.UserService.*(..))")
public void before(JoinPoint jp){
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName()
+ "方法。方法入参:" + Arrays.toString(jp.getArgs()));
} @AfterReturning(pointcut = "execution(* edu.cn.service.UserService.*(..))", returning = "returnValue")
public void afterReturning(JoinPoint jp, Object returnValue){
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName()
+ "方法。方法返回值:" + returnValue);
} } 

@Aspect等注解在aspectjweaver依赖下。在上述代码中,使用@Aspect注解将UserServiceLogger定义为切面,并且使用@Before注解将before()方法定义为前置增强,使用@AfterReturning方法将afterReturning()方法定于为后置增强

为了能够获得当前连接点的信息,在增强方法中添加了JoinPoint类型的参数,Spring会自动注入该实例。

对于后置增强,还可以定义一个参数用于接受目标方法的返回值。需要注意的是,必须在@AfterReturning注解中通过returning属性指定该参数的名称,Spring会将目标方法的返回值赋值给指定名称的参数。

1.1、对于相同的切入点要求,可以统一定义,以便于重用和维护,如下

package edu.cn.service;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.util.Arrays; @Aspect
public class UserServiceLogger {
private static final Logger log = LoggerFactory.getLogger(UserServiceLogger.class); @Pointcut("execution(* edu.cn.service.UserService.*(..))")
public void pointcut(){} @Before("pointcut()")
public void before(JoinPoint jp){
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName()
+ "方法。方法入参:" + Arrays.toString(jp.getArgs()));
} @AfterReturning(pointcut = "pointcut()", returning = "returnValue")
public void afterReturning(JoinPoint jp, Object returnValue){
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName()
+ "方法。方法返回值:" + returnValue);
} }

切入点表达式可以使用@Pointcut注解来表示,而切入点签名则需要通过一个普通的方法定义来提供,如上述代码中的pointcut()方法,作为切入点签名的方法必须返回void类型。定义好切入点后,就可以使用“pointcut()”签名进行引用

2、切面定义完后,还需要在Spring配置文件中完成织入工作,如下

只需在配置文件中添加<aop:aspectj-autoproxy/>元素,就可以启用对于@AspectJ注解的支持,Spring将自动为匹配的Bean创建代理

为了注册定义好的切面,还需在Spring配置文件中声明UserServiceLogger的一个实例。如果不需要被其他Bean引用,可以不指定id属性

<?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/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="service,dao"/>
<bean class="edu.cn.service.UserServiceLogger"></bean>
<aop:aspectj-autoproxy/>

</beans>

三、@AfterThrowing(异常抛出增强)、@After(最终增强)、@Around(环绕增强)注解进行增强的配置

1、@AfterThrowing(异常抛出增强)

使用@AfterThrowing注解可以定义异常抛出增强。如果需要获取抛出的异常,可以为增强方法声明相关类型的参数,并通过@AfterThrowing注解的throwing属性指定该参数名称,Spring会为其注入从目标方法抛出的异常实例,如下

package edu.cn.service;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; @Aspect
public class ErrorLogger {
private static final Logger log = LoggerFactory.getLogger(ErrorLogger.class); @AfterThrowing(pointcut = "execution(* edu.cn.service.UserService.*(..))", throwing = "e")
public void afterThrowing(JoinPoint jp, RuntimeException e){
log.error(jp.getSignature().getName() + "方法方法异常:" + e);
}
}

2、@After(最终增强)

使用@After注解可以定义最终增强

package edu.cn.service;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; @Aspect
public class AfterLogger {
private static final Logger log = LoggerFactory.getLogger(AfterLogger.class); @After("execution(* edu.cn.service.UserService.*(..))")
public void afterLogger(JoinPoint jp){
log.info(jp.getSignature().getName() + "方法结束执行。");
}
}

3、@Around(环绕增强)

使用@Around注解可以定义环绕增强。通过为增强方法声明ProceedingJoinPoint类型的参数,可以获得连接点信息。通过它的proceed()方法可以调用真正的目标方法,从而实现对连接点的完全控制。

package edu.cn.service;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.util.Arrays; @Aspect
public class AroundLogger {
private static final Logger log = LoggerFactory.getLogger(AroundLogger.class); @Around("execution(* edu.cn.service.UserService.*(..))")
public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable {
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName()
+ "方法。方法入参:" + Arrays.toString(jp.getArgs()));
try {
Object result = jp.proceed();
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName()
+ "方法。方法返回值:" + result);
} catch (Throwable e) {
log.error(jp.getSignature().getName() + "方法发生异常:" + e);
throw e;
}finally {
log.info(jp.getSignature().getName() + "方法结束执行。");
}
}
}

Spring使用注解实现AOP的更多相关文章

  1. Spring之注解实现aop(面向切面编程)

    1:Aop(aspect object programming)面向切面编程,名词解释:    1.1:功能:让关注点代码与业务逻辑代码分离    1.2:关注点        重复代码就叫做关注点  ...

  2. 阶段3 2.Spring_08.面向切面编程 AOP_9 spring基于注解的AOP配置

    复制依赖和改jar包方式 src下的都复制过来. 复制到新项目里了 bean.xml里面复制上面一行代码到下面.把aop改成context. 配置spring容器创建时要扫描的包 Service的配置 ...

  3. Spring 基于注解的AOP实现

    在本文开始之前,我要引入一张图,这张图的来源 https://blog.csdn.net/chenyao1994/article/details/79708496 ,版权归原作者所有,我借鉴了原作者的 ...

  4. Spring基于注解配置AOP

    D:\Java\IdeaProjects\JavaProj\SpringHelloWorld\src\aop.xml <?xml version="1.0" encoding ...

  5. 基于spring@aspect注解的aop实现

    第一步:编写切面类 package com.dascom.hawk.app.web.tool; import org.aspectj.lang.JoinPoint; import org.aspect ...

  6. Spring Annotation注解进行aop的学习

    使用Maven管理项目,pom文件为: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=" ...

  7. Spring的注解方式实现AOP

    Spring对AOP的实现提供了很好的支持.下面我们就使用Spring的注解来完成AOP做一个例子. 首先,为了使用Spring的AOP注解功能,必须导入如下几个包.aspectjrt.jar,asp ...

  8. 使用Spring的注解方式实现AOP

    Spring对AOP的实现提供了很好的支持.下面我们就使用Spring的注解来完成AOP做一个例子. 首先,为了使用Spring的AOP注解功能,必须导入如下几个包.aspectjrt.jar,asp ...

  9. spring学习笔记二 注解及AOP

    本节需要导入spring-aop包 注解 使用注解的目的是为了代替配置,在使用注解时,省略键时,则是为value赋值. 扫描某个包下的所有类中的注解 <?xml version="1. ...

随机推荐

  1. 关于博主&&联系博主

    关于我自己 天朝一名普通理科男高中生,现正读高二. 一位正在求学之路上奋斗的蒟蒻.很爱听歌,欧美为主,霉霉死粉.交际方面比较弱. 常用编辑器为DEV-C++,编译器为gcc,常用OJ是洛谷 基本熟练使 ...

  2. 小程序 swiper 轮播图滚动图片 + 视频

    直奔代码主题wxml: <view class="test_box"> <swiper indicator-dots="{{indicatorDots} ...

  3. python celery 异步学习

    1.运行redis 2.安装celery:pip install celery[redis] 3.vim task.py import time from celery import Celery b ...

  4. lcx用法

    lcx使用方 本机IP:192.168.125.11      目标机IP:192.168.125.101 本机运行: lcx -listen 3333  2222 目标机运行:lcx -slave ...

  5. 使用SpringBoot校验客户端传来的数据

    前端的数据校验都是辣鸡!后端天下第一! 很多时候我们后端需要前端传数据过来, 比如注册, 修改用户名, 修改密码等等.很可能有些用户就喜欢搞事, 喜欢发一大堆乱七八糟的数据到后端来, 甚至有些前端老哥 ...

  6. 代码优化-多态代替IF条件判断

    场景描述 在开发的场景中,常常会遇到打折的业务需求,每个用户对应的等级,他们的打折情况也是不一样的.例如普通会员打9折,青铜会员打8.5折,黄金会员打8折等等.在一般开发中最简单的就是判断用户的等级, ...

  7. LeetCode 130. 被围绕的区域(Surrounded Regions)

    题目描述 给定一个二维的矩阵,包含 'X' 和 'O'(字母 O). 找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充. 示例: X X X X X O O X X X ...

  8. 一、基础篇--1.3进程和线程-CountDownLatch、CyclicBarrier 和 Semaphore

    下面对上面说的三个辅助类进行一个总结: 1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: CountDownLatch一般用于某个线程A等待 ...

  9. Windows 全绿色安装Mysql

    1.从Oracle官网上下载Mysql的Windows安装包,注意要下载Zip文件 2.将Mysql的Zip文件下载到本地电脑指定目录下 3.配置my.inia. 在<安装目录>下创建一个 ...

  10. a标签的伪类

    a 超链接 伪类:给元素添加特殊的效果 :link 未访问过的链接初始颜色 :visited 访问过后的链接颜色 :hover 鼠标移入(悬停)时的颜色 :active 鼠标按下时链接的颜色 书写时的 ...