3.2.前置通知
MyMethodBeforeAdvice.java
package com.csdn.xw.aop.advice; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; import java.util.Arrays; /** * 买书、评论前加系统日志 * @author Administrator * */ public class MyMethodBeforeAdvice implements MethodBeforeAdvice { @Override public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { // 在这里,可以获取到目标类的全路径及方法及方法参数,然后就可以将他们写到日志表里去 String target = arg2.getClass().getName(); String methodName = arg0.getName(); String args = Arrays.toString(arg1); System.out.println("【前置通知:系统日志】:"+target+"."+methodName+"("+args+")被调用了"); } }
Spring-Context.xml
<!--目标对象--> <bean class="com.csdn.xw.aop.biz.impl.BookBizImpl" id="bookBiz"></bean> <!--前置通知--> <bean class="com.csdn.xw.aop.advice.MyMethodBeforeAdvice" id="methodBeforeAdvice"></bean> <!--代理--> <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean"> <!--配置目标对象--> <property name="target" ref="bookBiz"></property> <!--配置代理接口--> <property name="proxyInterfaces"> <list> <value>com.csdn.xw.aop.biz.IBookBiz</value> </list> </property> <!--配置通知--> <property name="interceptorNames"> <list> <value>methodBeforeAdvice</value> </list> </property> </bean>
Demo01.java(模拟)
package com.csdn.xw.aop.demo; import com.csdn.xw.aop.biz.IBookBiz; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author Java方文山 * @compay csdn_Java方文山 * @create 2023-08-17-16:14 */ public class demo01 { public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("/Spring-Context.xml"); IBookBiz bookbiz = (IBookBiz) context.getBean("proxyFactoryBean"); bookbiz.buy("Java方文山","《大话西游》",9.9d); bookbiz.comment("Java方文山","绝了"); } }
测试结果:
3.3.后置通知
MyAfterReturningAdvice.java
package com.csdn.xw.aop.advice; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; import java.util.Arrays; /** * 买书返利 * @author Administrator * */ public class MyAfterReturningAdvice implements AfterReturningAdvice { @Override public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { String target = arg3.getClass().getName(); String methodName = arg1.getName(); String args = Arrays.toString(arg2); System.out.println("【后置通知:买书返利】:"+target+"."+methodName+"("+args+")被调用了,"+"该方法被调用后的返回值为:"+arg0); } }
Spring-Context.xml
<!--目标对象--> <bean class="com.csdn.xw.aop.biz.impl.BookBizImpl" id="bookBiz"></bean> <!--后置通知--> <bean class="com.csdn.xw.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean> <!--代理--> <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean"> <!--配置目标对象--> <property name="target" ref="bookBiz"></property> <!--配置代理接口--> <property name="proxyInterfaces"> <list> <value>com.csdn.xw.aop.biz.IBookBiz</value> </list> </property> <!--配置通知--> <property name="interceptorNames"> <list> <value>myAfterReturningAdvice</value> </list> </property>
Demo01.java无变化我们直接看打印结果:
3.3.环绕通知
MyMethodInterceptor.java
package com.csdn.xw.aop.advice; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import java.util.Arrays; /** * 环绕通知 * 包含了前置和后置通知 * * @author Administrator * */ public class MyMethodInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation arg0) throws Throwable { String target = arg0.getThis().getClass().getName(); String methodName = arg0.getMethod().getName(); String args = Arrays.toString(arg0.getArguments()); System.out.println("【环绕通知调用前:】:"+target+"."+methodName+"("+args+")被调用了"); // arg0.proceed()就是目标对象的方法 Object proceed = arg0.proceed(); System.out.println("【环绕通知调用后:】:该方法被调用后的返回值为:"+proceed); return proceed; } }
Spring-Context.xml
<!--目标对象--> <bean class="com.csdn.xw.aop.biz.impl.BookBizImpl" id="bookBiz"></bean> <!--环绕通知--> <bean class="com.csdn.xw.aop.advice.MyMethodInterceptor" id="methodInterceptor"></bean> <!--代理--> <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean"> <!--配置目标对象--> <property name="target" ref="bookBiz"></property> <!--配置代理接口--> <property name="proxyInterfaces"> <list> <value>com.csdn.xw.aop.biz.IBookBiz</value> </list> </property> <!--配置通知--> <property name="interceptorNames"> <list> <value>methodInterceptor</value> </list> </property> </bean>
Demo01.java无变化我们直接看打印结果:
3.4.异常通知
MyThrowsAdvice.java
package com.csdn.xw.aop.advice; import com.csdn.xw.aop.exception.PriceException; import org.springframework.aop.ThrowsAdvice; /** * 出现异常执行系统提示,然后进行处理。价格异常为例 * @author Administrator * */ public class MyThrowsAdvice implements ThrowsAdvice { public void afterThrowing(PriceException ex) { System.out.println("【异常通知】:当价格发生异常,那么执行此处代码块!!!"); } }
Spring-Context.xml
<!--目标对象--> <bean class="com.csdn.xw.aop.biz.impl.BookBizImpl" id="bookBiz"></bean> <!--异常通知--> <bean class="com.csdn.xw.aop.advice.MyThrowsAdvice" id="advice"></bean> <!--代理--> <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean"> <!--配置目标对象--> <property name="target" ref="bookBiz"></property> <!--配置代理接口--> <property name="proxyInterfaces"> <list> <value>com.csdn.xw.aop.biz.IBookBiz</value> </list> </property> <!--配置通知--> <property name="interceptorNames"> <list> <value>advice</value> </list> </property> </bean>
Demo01.java(模拟)我们将价格改为负数
package com.csdn.xw.aop.demo; import com.csdn.xw.aop.biz.IBookBiz; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author Java方文山 * @compay csdn_Java方文山 * @create 2023-08-17-16:14 */ public class demo01 { public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("/Spring-Context.xml"); IBookBiz bookbiz = (IBookBiz) context.getBean("proxyFactoryBean"); bookbiz.buy("Java方文山","《大话西游》",-9.9d); bookbiz.comment("Java方文山","绝了"); } }
测试结果:
3.4.过滤通知
Spring-Context.xml
<!--目标对象--> <bean class="com.csdn.xw.aop.biz.impl.BookBizImpl" id="bookBiz"></bean> <!--后置通知--> <bean class="com.csdn.xw.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean> <!--过滤配置--> <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="regexpMethodPointcutAdvisor"> <property name="advice" ref="myAfterReturningAdvice"></property> <property name="pattern" value=".*buy"></property> </bean> <!--代理--> <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean"> <!--配置目标对象--> <property name="target" ref="bookBiz"></property> <!--配置代理接口--> <property name="proxyInterfaces"> <list> <value>com.csdn.xw.aop.biz.IBookBiz</value> </list> </property> <!--配置通知--> <property name="interceptorNames"> <list> <value>regexpMethodPointcutAdvisor</value> </list> </property> </bean>
测试结果:
四、总结
Q:谈谈你对aop的理解?
A:aop是面向切面编程,程序是由上至下执行,但是aop面向切面编程不是,aop的程序执行,首先当程序执行到目标对象的目标方法时,如果连接点上有前置通知,则先执行前置通知,再执行目标方法,如果没有前置通知,则继续执行目标方法,再查看目标方法上有无后置通知,如果有,则再进行执行后置通知。
不管是前置通知、后置通知、环绕通知、异常通知、过滤通知,代码都是非业务核心代码,如日志、事物的管理。
到这里我的分享就结束了,欢迎到评论区探讨交流!!
如果觉得有用的话还请点个赞吧 ♥ ♥