时间:2021-05-19
在使用AOP的时候遇到了一些问题,特此记录一下
首先写一个常用的AOP切片
切片类AopLog
package com.mantis.aop.aspect;import com.fasterxml.jackson.databind.ObjectMapper;import com.mantis.aop.common.util.DataUtil;import eu.bitwalker.useragentutils.UserAgent;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.validation.BeanPropertyBindingResult;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.ArrayList;import java.util.Arrays;import java.util.Enumeration;import java.util.List;import java.util.stream.Collectors;/** * @Description:执行顺序 正常顺序 Around Before Method.invoke Around After AfterReturning * 异常顺序 Around Before Method.invoke After AfterThrowing * @author: wei.wang * @since: 2020/4/4 13:47 * @history: 1.2020/4/4 created by wei.wang */@Aspect@Componentpublic class AopLog { private static Logger logger = LoggerFactory.getLogger(AopLog.class); /** * 定义切点,切点为com.smec.fin.controller包和子包里任意方法的执行和service层所有方法的执行 */ @Pointcut("execution(public * com.mantis.aop.controller..*.*(..))") public void log() { // 定义切点 } /** * 定义切点,切点为com.smec.fin.controller包和子包里任意方法的执行和service层所有方法的执行 */ @Pointcut("execution(public * com.mantis.aop.service.impl..*.*(..))") public void log2() { // 定义切点 } /** * 环绕通知 * * @param point * @return * @throws Throwable */ @Around("log2()") public Object aroundLog(ProceedingJoinPoint point) throws Throwable { logger.info("开始执行环绕操作"); Object result = point.proceed(); logger.info("执行环绕操作结束,返回值:{}", result); return result; }}服务类AopServiceImpl
package com.mantis.aop.service.impl;import com.mantis.aop.service.AopService;import org.springframework.aop.framework.AopContext;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/** * @Description: * @author: wei.wang * @since: 2020/10/24 12:45 * @history: 1.2020/10/24 created by wei.wang */@Servicepublic class AopServiceImpl implements AopService { @Override public void testAop(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testAop" + str); this.testAop2("testFinalMethod"); } @Override public void testAop2(String str) { //this.testFinalMethod("testFinalMethod"); System.out.println("com.mantis.aop.service.AopService.AopServiceImpl." + str); } public final void testFinalMethod(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethod" + str); } public void testFinalMethod2(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethod" + str); }}1.同方法运行问题
在使用AOP时我们发现存在同类中调用时切点失效问题,在执行时我们发现只执行了testAop的切点,testAop2的切点没有执行,这是因为经过AOP代理后的对象都已经不是原来的对象了,而是加入了增强方法的代理对象,使用代理对象调用时可以执行增强方法,但是这里是使用this调用的,也就是AopServiceImpl,因为不是代理对象就没有增强方法。
2020-10-24 13:31:06.261 INFO 13344 --- [nio-9000-exec-1] com.mantis.aop.controller.AopController : 方法开始执行2020-10-24 13:31:06.264 INFO 13344 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 开始执行环绕操作com.mantis.aop.service.AopService.AopServiceImpl.testAoptest2com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethod2020-10-24 13:31:06.274 INFO 13344 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 执行环绕操作结束,返回值:null用@Autowired或Resource引入自身依赖
使用注解方法引入自身代理依赖,注意使用构造的方式会有循环依赖问题
@Autowired AopServiceImpl aopService; @Override public void testAop(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testAop" + str); aopService.testAop2("testFinalMethod"); System.out.println(); }2020-10-24 13:36:33.477 INFO 12528 --- [nio-9000-exec-1] com.mantis.aop.controller.AopController : 方法开始执行2020-10-24 13:36:33.480 INFO 12528 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 开始执行环绕操作com.mantis.aop.service.AopService.AopServiceImpl.testAoptest22020-10-24 13:36:33.488 INFO 12528 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 开始执行环绕操作com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethod2020-10-24 13:36:33.488 INFO 12528 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 执行环绕操作结束,返回值:null2020-10-24 13:36:33.490 INFO 12528 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 执行环绕操作结束,返回值:null开启暴露代理类,AopContext.currentProxy()方式获取代理类
通过暴露代理类方式,实际原理是把代理类添加到当前请求的ThreadLocal里面,然后在使用时从ThreadLocal中获取代理类,再调用对应的方法
在主方法上加入@EnableAspectJAutoProxy(exposeProxy=true),然后从AOP上下文中获取代理
@Override public void testAop(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testAop" + str); AopServiceImpl service = AopContext.currentProxy() != null ? (AopServiceImpl) AopContext.currentProxy() : this; service.testAop2("testFinalMethod"); System.out.println(); }2020-10-24 13:38:31.031 INFO 18828 --- [nio-9000-exec-1] com.mantis.aop.controller.AopController : 方法开始执行2020-10-24 13:38:31.035 INFO 18828 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 开始执行环绕操作com.mantis.aop.service.AopService.AopServiceImpl.testAoptest22020-10-24 13:38:31.047 INFO 18828 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 开始执行环绕操作com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethod2020-10-24 13:38:31.048 INFO 18828 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 执行环绕操作结束,返回值:null2020-10-24 13:38:31.050 INFO 18828 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 执行环绕操作结束,返回值:null2.final关键字问题
Spring AOP默认使用cglib,会生成目标对象的子类代理对象。调用目标对象的方法,实际上是调用代理对象的方法。由于子类能够继承父类的方法,因此一般情况下目标类的方法,代理对象都会有。但是当目标类中某个方法带有final关键字时,这个方法不能被重写,因此代理对象中没有这个方法,因此会调用目标对象的方法。
带final关键字
因为testFinalMethod方法中存在final关键字,导致无法重写,结果代理对象就无法生成这个方法,因此调用目标对象方法,导致没有被增强
@Override public void testAop(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testAop" + str); AopServiceImpl service = AopContext.currentProxy() != null ? (AopServiceImpl) AopContext.currentProxy() : this; service.testFinalMethod("testFinalMethod"); System.out.println(); } public final void testFinalMethod(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethod" + str); }2020-10-24 13:47:46.907 INFO 15204 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 开始执行环绕操作com.mantis.aop.service.AopService.AopServiceImpl.testAoptest2com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethodtestFinalMethod2020-10-24 13:47:46.916 INFO 15204 --- [nio-9000-exec-1] com.mantis.aop.aspect.AopLog : 执行环绕操作结束,返回值:null不带final关键字
因为testFinalMethod方法中不存在final关键字,所以正常执行增强。
@Override public void testAop(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testAop" + str); AopServiceImpl service = AopContext.currentProxy() != null ? (AopServiceImpl) AopContext.currentProxy() : this; service.testFinalMethod2("testFinalMethod"); System.out.println(); } public final void testFinalMethod2(String str) { System.out.println("com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethod" + str); }2020-10-24 13:50:51.018 INFO 13532 --- [nio-9000-exec-2] com.mantis.aop.controller.AopController : 方法开始执行2020-10-24 13:50:51.021 INFO 13532 --- [nio-9000-exec-2] com.mantis.aop.aspect.AopLog : 开始执行环绕操作com.mantis.aop.service.AopService.AopServiceImpl.testAoptest22020-10-24 13:50:51.029 INFO 13532 --- [nio-9000-exec-2] com.mantis.aop.aspect.AopLog : 开始执行环绕操作com.mantis.aop.service.AopService.AopServiceImpl.testFinalMethodtestFinalMethod2020-10-24 13:50:51.030 INFO 13532 --- [nio-9000-exec-2] com.mantis.aop.aspect.AopLog : 执行环绕操作结束,返回值:null2020-10-24 13:50:51.031 INFO 13532 --- [nio-9000-exec-2] com.mantis.aop.aspect.AopLog : 执行环绕操作结束,返回值:null总结
到此这篇关于Spring AOP使用时的一些问题汇总的文章就介绍到这了,更多相关Spring AOP使用时的问题内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
一、背景 由于公司业务需要动态配置一些存储过程来生成数据,之前尝试过使用jpa来完成,或多或少都存在一些问题,最后使用了spring的Jdbctemplate
spring对AOP的实现提供了很好的支持。下面我们就使用Spring的注解来完成AOP做一个例子。首先,为了使用Spring的AOP注解功能,必须导入如下几个
spring的事务控制本质上是通过aop实现的。在springboot中使用时,可以通过注解@Transactional进行类或者方法级别的事务控制,也可以自己
导语:个人对网络连接接触的不多,在使用时自己发现一些问题,记录一下。正文:我在使用HttpURLConnection.getResponseCode()的时候直
spring的事务控制本质上是通过aop实现的。在springboot中使用时,可以通过注解@Transactional进行类或者方法级别的事务控制,也可以自己