这篇“Spring AOP如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring AOP如何使用”文章吧。
@Repository("userDao")
public class UserDao {
public void addUser() {
System.out.println("???? 拦截的方法 addUser 开始执行");
}
}
@Aspect
@Component
public class AnnotationAspect {
// 定义切入点表达式, 使用一个返回值为 void、方法体为空的方法来命名切入点
@Pointcut("execution(* com.fairy.springmvc.aspectj.annotation.*.*(..))")
private void customPointCut(){}
// 前置通知
@Before("customPointCut()")
public void myBefore(JoinPoint joinPoint){
System.out.print("前置通知:模拟执行权限检查..,");
System.out.print("目标类是:" + joinPoint.getTarget());
System.out.println(",被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());
}
// 后置通知
@AfterReturning(value="customPointCut()")
public void myAfterReturning(JoinPoint joinPoint) {
System.out.print("后置通知:模拟记录日志..,");
System.out.println("被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());
}
/**
* 环绕通知
* ProceedingJoinPoint 是 JoinPoint的子接口,表示可执行目标方法
* 1.必须是 Object 类型的返回值
* 2.必须接收一个参数,类型为 ProceedingJoinPoint
* 3.必须 throws Throwable
*/
@Around("customPointCut()")
public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
// 开始
System.out.println("环绕开始:执行目标方法之前,模拟开启事务..,");
// 执行当前目标方法
Object obj = proceedingJoinPoint.proceed();
// 结束
System.out.println("环绕结束:执行目标方法之后,模拟关闭事务..,");
return obj;
}
/**
* 异常通知处理
* @param joinPoint
* @param e
*/
@AfterThrowing(value="customPointCut()",throwing="e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e){
System.out.println("异常通知:出错了" + e.getMessage());
}
// 最终通知
@After("customPointCut()")
public void myAfter(){
System.out.println("最终通知:模拟方法结束后释放资源..");
}
}
开启@AspectJ
的注解配置方式,有两种方式
1 在 xml
文件,添加以下配置:
<!-- 启动基于注解的声明式 AspectJ 支持 -->
<aop:aspectj-autoproxy />
2 使用了 Java
代码风格的配置,则需使用 EnableAspectJAutoProxy
注解
示例如下
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.fairy.springmvc")
public class ApplicationConfig {
....
}
public class TestCase {
@Test
public void testAnnotation() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"spring-test.xml");
// 从容器中获得内容
UserDao userDao= (UserDao) applicationContext.getBean("userDao");
// 执行方法
userDao.addUser();
}
}
运行结果如下:
环绕开始:执行目标方法之前,模拟开启事务..,
前置通知:模拟执行权限检查..,
目标类是:com.fairy.springmvc.aspectj.annotation.UserDao@4a699efa,
被植入增强处理的目标方法为:addUser
???? 拦截的方法 addUser 开始执行
后置通知:模拟记录日志..,被植入增强处理的目标方法为:addUser
最终通知:模拟方法结束后释放资源..
环绕结束:执行目标方法之后,模拟关闭事务..,
通过输出结果看出,符合预期。
@Repository("companyDao")
public class CompanyDao {
public void addCompany() {
System.out.println("???? 真正的业务处理:add company ????");
}
public void exception() throws Exception {
throw new Exception("业务异常了");
}
}
@Component("xmlAspectConfig")
public class XmlAspect {
public void printUnderscore() {
System.out.println("------------------------------------------------");
}
/**
* 在核心业务执行前执行,不能阻止核心业务的调用
* @param joinPoint
*/
public void beforeAdvice(JoinPoint joinPoint) {
printUnderscore();
System.out.println("1️⃣ 通知:beforeAdvice 执行开始");
System.out.println(" 执行核心业务逻辑前,可以做一些前置的安全性的检测等");
System.out.println(" 通知:beforeAdvice 执行结束");
printUnderscore();
}
/**
* 核心业务退出后,不管是正常结束还是异常退出,均执行此通知
* @param joinPoint
*/
public void afterAdvice(JoinPoint joinPoint) {
printUnderscore();
System.out.println("4️⃣ 通知:afterAdvice 执行开始");
System.out.println(" 此处可以对返回值做进一步的处理");
System.out.println(" 通知:afterAdvice 执行结束");
}
/**
* 核心业务调用正常退出后,不管是否有返回值,只要是正常退出,都会执行此通知
* @param joinPoint
*/
public void afterReturningAdvice(JoinPoint joinPoint) {
printUnderscore();
System.out.println("2️⃣ 通知:afterReturningAdvice 执行开始");
System.out.println(" 此处可以对返回值做进一步处理");
System.out.println(" 通知:afterReturningAdvice 执行结束");
}
/**
* 核心业务逻辑调用异常退出后,执行此通知,处理错误信息
* @param e
*/
public void afterThrowingAdvice(Exception e) {
printUnderscore();
System.out.println("3️⃣ 通知:afterThrowingAdvice 执行开始");
System.out.println(" 错误信息:" + e.getMessage());
System.out.println(" 此处意味着,在核心业务逻辑出错时,捕获异常,并可以做一些日志记录相关的操作");
}
/**
* 手动控制调用核心业务逻辑,以及调用前和调用后的处理
* @param pjp
*/
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
// 开始
System.out.println("5️⃣ 环绕开始:执行目标方法之前");
System.out.println(" 此处可以做类似于 Before Advice 的事情");
// 调用核心逻辑,执行当前目标方法
Object obj = pjp.proceed();
// 打印下划线
printUnderscore();
// 结束
System.out.println(" 此处可以做类似于 After Advice 的事情");
System.out.println("5️⃣ 环绕结束:执行目标方法之后");
return obj;
}
}
<!-- 基于 XML 文件的配置进行声明,注意和 aop:aspectj-autoproxy 的区别 -->
<aop:config proxy-target-class="true">
<!-- 基于 aspect 配置一个完整的切面 -->
<aop:aspect id="aspectXmlConfigExample" ref="xmlAspectConfig">
<!-- 切点配置,可以配置多个切点 -->
<aop:pointcut id="xmlPointCut"
expression="execution(* com.fairy.springmvc.aspectj.xml.CompanyDao.*(..))"/>
<aop:after-returning method="afterReturningAdvice" pointcut-ref="xmlPointCut" />
<aop:after-throwing method="afterThrowingAdvice" pointcut-ref="xmlPointCut" throwing="e"/>
<aop:after method="afterAdvice" pointcut-ref="xmlPointCut" />
<aop:around method="aroundAdvice" pointcut-ref="xmlPointCut" />
<aop:before method="beforeAdvice" pointcut-ref="xmlPointCut" />
</aop:aspect>
</aop:config>
注意:
值得注意的是
around
与before
和after
的执行顺序。3
者的执行顺序取决于在xml
中的配置顺序。
public class TestCase {
@Test
public void testAnnotation() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"spring-test.xml");
CompanyDao companyDao = (CompanyDao) applicationContext.getBean("companyDao");
companyDao.addCompany();
// companyDao.exception();
}
}
输出结果如下:
-------------------------------
5️⃣ 环绕开始:执行目标方法之前
此处可以做类似于 Before Advice 的事情
------------------------------------------------
1️⃣ 通知:beforeAdvice 执行开始
执行核心业务逻辑前,可以做一些前置的安全性的检测等
通知:beforeAdvice 执行结束
------------------------------------------------
???? 真正的业务处理:add company ????
------------------------------------------------
2️⃣ 通知:afterReturningAdvice 执行开始
此处可以对返回值做进一步处理
通知:afterReturningAdvice 执行结束
------------------------------------------------
4️⃣ 通知:afterAdvice 执行开始
此处可以对返回值做进一步的处理
通知:afterAdvice 执行结束
------------------------------------------------
此处可以做类似于 After Advice 的事情
5️⃣ 环绕结束:执行目标方法之后
结果符合预期。
以上就是关于“Spring AOP如何使用”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。