Spring Aop
AOP
底层用的仍然是jdk的动态代理
切面表达式
符号 | 意义 |
---|---|
* | 0至多个任意字符 |
.. | 用在方法参数中,表示任意多个参数;用在包名后,表示当前包及其子包路径 |
+ | 用在类名后,表示当前类及其子类;用在接口后,表示当前接口及其实现类 |
举例:
-
规则:execytion(访问权限 方法返回值 方法声明(参数) 异常类型)
-
execution(public * *(..))
- 指定切入点为:任意公共方法
-
execution(* set*(..))
- 指定切入点为:任何一个以“set”开始的方法。
-
execution(* com.xyz.service.*.*(..))
- 指定切入点为:定义在service包里的任意类的任意方法。
-
execution(* com.xyz.service..*.*)
- 指定切入点为:定义在service包或者子包里面的任意类的任意方法。“。。”出现在包名时,后面必须跟“*”,表示包、子包下的所有类。
-
execution(* *..service.*.*(..))
- 指定所有包下的service子包下所有类(接口)中所有方法为切入点
-
execution(* *.service.*.*(..))
- 指定只有一级包下的service子包下所有类(接口)中所有方法为切入点
代理例子:
-
目标接口
public interface SomeService{ void doSome(String name,Integer age); String doOther(String name,Integer age); String doFirst(String name,Integer age); void doSecond(); void doTird(); }
-
目标对象
public SomeServiceImpl implements SomeService{ public void doSome(String name,Integer age){ System.out.println("doSome==="+"name= "+name+"; age= "+age) } public String doOther(String name,Integer age){ System.out.println("doOther==="+"name= "+name+"; age= "+age) return "abc"; } public String doFirst(String name,Integer age){ System.out.println("doFirst==="+"name= "+name+"; age= "+age) return "doFirst"; } public void doSecond(){ System.out.println("doSecond"+10/0) } public void doTird(){ System.out.println("doThird"); } }
-
切面类
@Aspect public class MyAspect{ //公共方法 方法参数必须是固定的 执行时间before 执行位置 execution //JoinPoint必须再第一个参数 @Before(value = "execution(public void com.*.ba01.SomeServiceImpl.dosome(String,Integer))") public void myBefore(JoinPoint jp){ System.out.println("方法的签名"+jp.getSignature()); System.out.println("方法的名称"+jp.getSignature().getName()); System.out.println("前置:切面功能,再目标方法执行之前输出执行时间"+ new Date()); } //公共方法,没有返回值,方法有参数 @AfterReturning(value:"execution=(* *..SomeserviceImpl.doSome(..))",returning) public void myAfterReturing(JoinPoint jp,Object res){ System.out.println("后置通知,再目标方法执行之后执行"+res) } /** 环绕通知 功能最强的通知,在目标方法的前和后都增强功能。控制目标方法是否被调用执行 修改原来的目标方法的执行结果。影响最后的调用结果 等同于jdk InvocationHandler接口 **/ @Around(vlaue="execution(* *..SomeServiceImpl.doFirst(..))") public Object myAround(ProceedingJoinPoint pjp){ String name = ""; Object result = null; result = pjp.proceed(); //获取参数 Object args[] = pjp.getArgs(); if(args!=null&&args.length()>1){ Object arg = args[0]; name = (Stirng) arg; } System.out.println("环绕通知,目标方法执行之前的时间"+ new Date()); //目标方法的调用 pjp.proceed(); // method.invoke(); System.out.println("环绕通知,目标方法执行之后"); //改变目标输出结果 if(result!=null){ result = "修改后的内容"; } return result; } @AfterThrowing(value="execution(* *..SomeServiceImpl.doSecond(..)") public void afterThrowing(Exception ex){ System.out.println("异常通知:方法执行发生异常:"+ex.getMessage()); } @After(value="execution=(* *..SomeServiceImpl.dothird(..))") public void after(){ System.out.println("最终通知"); } @Pointcut(value="execution=(* *..SomeserviceImpl.doThired(..))") public void mypt(){ } @After(value="mypt()") public void testPoincut(){ } }
-
xml applicationContext.xml
<bean id="someService" class="someServiceImpl"></bean> <bean id="myAspect" class="MyAspect"></bean> <!--声明自动代理生成器--> <aop:aspectj-qutoproxy /> <!--如果要使用CJLIB需要使用下面这个--> <aop:aspectj-qutoproxy proxy-target-class="true"/>
有接口使用jdk的InvocationHandler 没有接口使用CGLIB方式
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!