SpringAOP切入方式
AOP与OOP是什么关系?
AOP的实现技术有多种,其中与Java无缝对接的是一种称为AspectJ的技术,Spring AOP 与AspectJ 实现原理上并不完全一致,但功能上是相似的。AOP的出现确实解决外围业务代码与核心业务代码分离的问题,但它并不会替代OOP,如果说OOP的出现是把编码问题进行模块化,那么AOP就是把涉及到众多模块的某一类问题进行统一管理
切面(Aspect)包含了切点(PointCut)、连接点(JoinPoint);额外还有通知(Advice),织入(Weaving),引入(Introduce)。
package springMVCmybatis.com.my.aop;import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterRetuing; import org.aspectj.lang.annotation.AfterThrowing; import org.springframework.core.annotation.Order;@Aspect// 切面执行顺序@Order(3)public class MyAopTest { @Pointcut("execution(* springMVCmybatis..addController.addEmp(..))") private void pointCutMethod() { } @Pointcut("execution(* springMVCmybatis.com.my.aop.UserServiceImp.*(..))") private void testAOP() { } /** 声明前置通知 ,JoinPont是srpring提供的静态变量,* 通过joinPoint参数可以获得目标方法的类名,方法参数,方法名等信息,这个参数可有可无。*/@Before("pointCutMethod() || testAOP()") public void doBefore(JoinPoint joinPoint) { System.out.println("@Before:开始添加--order=3"); }//声明后置通知 ,如果result的类型与proceed执行的方法返回的参数类型不匹配那么就不会执行这个方法@AfterRetuing(pointcut = "pointCutMethod() || testAOP()", retuing = "result") public void doAfterRetuing(String result) { System.out.println("@AfterRetuing:后置通知--order=3"); System.out.println("---" + result + "---"); }//声明例外通知 @AfterThrowing(pointcut = "pointCutMethod() || testAOP()", throwing = "e") public void doAfterThrowing(Exception e) { System.out.println("@AfterThrowing:例外通知--order=3"); System.out.println(e.getMessage()); }//声明最终通知 @After("pointCutMethod() || testAOP()") public void doAfter() { System.out.println("@After:最终通知--order=3"); }/** 声明环绕通知* 参数必须是ProceedingJoinPoint,通过该对象的proceed()方法来执行目标函数,* proceed()的返回值就是环绕通知的返回值,proceedingJoinPoint是个接口,* implement JoinPoint,所以也可以获得目标函数的类名,方法名等参数。*/ @Around("pointCutMethod() || testAOP()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("@Around:进入方法---环绕通知--order=3"); Object o = pjp.proceed(); System.out.println("@Around:退出方法---环绕通知--order=3"); retu o; } }
上面是我写的一个例子,结合例子我们来看看这些核心的概念:
2.1、切面(Aspect):是一个类,里面定义了通知与切点。
2.2、切点(PointCut):表达式(表达式有很多种,如方法签名表达式,类型签名表达式,还有其他的表达式,)。就是告诉程序要在执行哪些核心业务的时候,执行非核心的业务。
2.3、通知(advice):五种通知方式:
@Before
:前置通知,在调用目标方法之前执行通知定义的任务@After
:后置通知,在目标方法执行结束后,无论执行结果如何都执行通知定义的任务@After-retuing
:后置通知,在目标方法执行结束后,如果执行成功,则执行通知定义的任务@After-throwing
:异常通知,如果目标方法执行过程中抛出异常,则执行通知定义的任务@Around
:环绕通知,在目标方法执行前和执行后,都需要执行通知定义的任务。
3.1:方法签名表达式
1 2 |
|
其实如果单纯的给定这个表达式还是不容易记忆,下面对比方法的定义来记忆,一个java方法的全部定义方式可以表示成下面的方式:
public
String springMVCmybatic.com.my.aop.UserServiceImp(String a,
int
b)
throw
Exception{
}
- modifier-patte?:表示方法的修饰符,可有可无;对应的就是 public
- ret-type-patte:表示方法的返回值;对应的就是 String
- fully-qualified-class-name 方法所在类的完全限定名称;对应的就是 springMVCmybatic.com.my.aop.UserServiceImp
- param-patte:表示方法的参数;对应的就是 String a, int b
- throws-patte:表示方法抛出的异常,可有可无;对应的就是 throw Exception
3.2:&&,||,!
1 2 3 4 5 6 7 |
|
表达式之间可以采用与,或,非的方式来过滤。
四:多个切点的执行顺序
上面的例子中,定义了order=3,重新创建一个切面,定义order=6,执行的结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
从结果中可以看出order越小越先执行,执行完了之后就order越小就越后推出。总结为下面的图:
接口切入方式
实现类(全文通用)
package com.pb.entity;/** * 实体类 */public class Hello {private String name;private String password;public void show(){System.out.println("姓名 :"+this.getName()+"密码: "+this.getPassword());}public String getName() {retu name;}public void setName(String name) {this.name = name;}public String getPassword() {retu password;}public void setPassword(String password) {this.password = password;}}
1.1、前置增强
package com.pb.aop;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;/** * 前置增强的Bean * @author Administrator *实现MethodBeforeAdvice接口 */public class BeforeAdded implements MethodBeforeAdvice {@Overridepublic void before(Method arg0, Object[] arg1, Object arg2)throws Throwable {System.out.println("====前置增强!=====");}}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!--hello Bean --><bean id="hello" class="com.pb.entity.Hello" p:name="张三" p:password="123qwe"/><!--切入的Bean --><bean id="beforeAdd" class="com.pb.aop.BeforeAdded"/><!--前置增强切入的Bean --><aop:config><!-- 切入点 --><aop:pointcut expression="execution(* com.pb.entity.Hello.*(..))" id="myPoint"/><!-- 关联切入类和切入点 --><aop:advisor advice-ref="beforeAdd" pointcut-ref="myPoint"/></aop:config></beans>
1.2、后置增强
package com.pb.aop;import java.lang.reflect.Method;import org.springframework.aop.AfterRetuingAdvice;/** * 后置增强 */public class AfterAdded implements AfterRetuingAdvice {@Overridepublic void afterRetuing(Object arg0, Method arg1, Object[] arg2,Object arg3) throws Throwable {System.out.println("====这里是后置增强!====");}}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!--hello Bean --><bean id="hello" class="com.pb.entity.Hello" p:name="张三" p:password="123qwe"/><!--切入的Bean --><!--后置增强切入的Bean --><bean id="afterAdd" class="com.pb.aop.AfterAdded"/><aop:config><!-- 切入点 --><aop:pointcut expression="execution(* com.pb.entity.Hello.*(..))" id="myPoint"/><!-- 关联后置增强切入类和切入点 --><aop:advisor advice-ref="afterAdd" pointcut-ref="myPoint"/></aop:config><!--后置增强切入的Bean --></beans>
1.3、异常增强
实体类中增加异常
package com.pb.entity;/** * 实体类 */public class Hello {private String name;private String password;public void show(){System.out.println("姓名 :"+this.getName()+"密码: "+this.getPassword());//加入异常System.out.println(1/0);}public String getName() {retu name;}public void setName(String name) {this.name = name;}public String getPassword() {retu password;}public void setPassword(String password) {this.password = password;}}
package com.pb.aop;import java.lang.reflect.Method;import org.springframework.aop.ThrowsAdvice;/** * 异常增强类 * @author Administrator * */public class ThrowingAdded implements ThrowsAdvice {//第一种写法public void afterThrowing(Exception ex){System.out.println("我是异常增强!,,没处理异常,有问题就找我");}//第二种写法public void afterThrowing(Method arg0, Object[] arg1, Object arg2,Exception ex){System.out.println("我是异常增强!,,没处理异常,有问题就找我");}}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!--hello Bean --><bean id="hello" class="com.pb.entity.Hello" p:name="张三" p:password="123qwe"/><!--切入的Bean --><!--异常增强切入的Bean --><bean id="throwAdd" class="com.pb.aop.ThrowingAdded"/><aop:config><!-- 切入点 --><aop:pointcut expression="execution(* com.pb.entity.Hello.*(..))" id="myPoint"/><!-- 关联异常增强切入类和切入点 --><aop:advisor advice-ref="throwAdd" pointcut-ref="myPoint"/></aop:config></beans>
1.4、以上综合
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!--hello Bean --><bean id="hello" class="com.pb.entity.Hello" p:name="张三" p:password="123qwe"/><!--切入的Bean --><!--前置增强切入的Bean --><bean id="beforeAdd" class="com.pb.aop.BeforeAdded"/><!--后置增强切入的Bean --><bean id="afterAdd" class="com.pb.aop.AfterAdded"/><!--异常增强切入的Bean --><bean id="throwAdd" class="com.pb.aop.ThrowingAdded"/><aop:config><!-- 切入点 --><aop:pointcut expression="execution(* com.pb.entity.Hello.*(..))" id="myPoint"/><!-- 关联前置增强切入类和切入点 --><aop:advisor advice-ref="beforeAdd" pointcut-ref="myPoint"/><!-- 关联后置增强切入类和切入点 --><aop:advisor advice-ref="afterAdd" pointcut-ref="myPoint"/><!-- 关联异常增强切入类和切入点 --><aop:advisor advice-ref="throwAdd" pointcut-ref="myPoint"/></aop:config></beans>
1.5、环绕增强
package com.pb.aop;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;/** * 环绕增强 * @author Administrator *实现接口MethodIntercepor */public class AroundAdded implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation arg0) throws Throwable {Object result=null;try {System.out.println("环绕增强开始!"); result=arg0.proceed();System.out.println("环绕增强结束!");} catch (Exception e) {System.out.println("环绕增强异常!");}finally{System.out.println("环绕增强最终增强!");}retu result;}}
applicationContext.xml
<?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:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!-- 关联Bean Hello --><bean id="hello" class="com.pb.entity.Hello" p:name="张三" p:password="qewr"/><!--环绕增强的Bean --><bean id="aroundAdded" class="com.pb.aop.AroundAdded"></bean><aop:config><!-- 切入点--><aop:pointcut expression="execution(* com.pb.entity.*.*(..))" id="myPoint"/><!--关联切入点 --><aop:advisor advice-ref="aroundAdded" pointcut-ref="myPoint"/></aop:config></beans>
二、注解方式
package com.pb.aop;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.AfterRetuing;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;/** * 注解的方式现实AOP * @author Administrator * */@Aspectpublic class MyAnnotionAOP {/* * 前置 */@Before(value="execution(* com.pb.entity.*.*(..))")public void before(JoinPoint point){System.out.println("前置增强");System.out.println(point.getClass());}/* * 后置 */@AfterRetuing(value="execution(* com.pb.entity.*.*(..))")public void after(JoinPoint point){System.out.println("后置增强");//参数个数System.out.println(point.getArgs().length);}/* *异常 */@AfterThrowing(value="execution(* com.pb.entity.*.*(..))")public void afterThrowing(JoinPoint point){System.out.println("我是异常增强");System.out.println(point.getSignature().getName());}/** * 环绕 */@Around(value="execution(* com.pb.entity.*.*(..))")public Object myAround(ProceedingJoinPoint point){Object result=null;try {System.out.println("环绕增强开始了");System.out.println(point.getKind()+point.getArgs());point.proceed();System.out.println("环绕增强后置增强了");System.out.println(point.getTarget()+""+point.getClass());} catch (Throwable e) {System.out.println("环绕增强,异常增强处理");e.printStackTrace();}finally{System.out.println("环绕增强最终增强");}retu result;}}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!-- 关联Bean Hello --><bean id="hello" class="com.pb.entity.Hello" p:name="张三" p:password="qewr"/><!-- 切入 类 --><bean id="myAnnAOP" class="com.pb.aop.MyAnnotionAOP" /><!--开启自动代理 --><aop:aspectj-autoproxy/></beans>
三、Schema方式(推荐)
package com.pb.aop;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;/** * SCHEMA方式切入类 * * @author Administrator * */public class MySchemaAOP {/** * 前置切入 可以有参数但是固定写法 */public void before(JoinPoint point){System.out.println("这里是前置增强切入");System.out.println(point.getKind()+point.getArgs().toString());}/** * 后置切入 */public void after(JoinPoint point){System.out.println("这里是后置增强切入");System.out.println(point.getTarget()+point.getSignature().getName());}/** * 异常切入 */public void myException(JoinPoint point){System.out.println("这里是异常增强切入");System.out.println(point.getSourceLocation());}/** * 环绕增强切入 */public Object myAround(ProceedingJoinPoint point){Object resut=null;try {System.out.println("环绕增强---前置增强");resut=point.proceed();System.out.println("环绕增强---后置增强");} catch (Throwable e) {System.out.println("环绕增强---异常增强");e.printStackTrace();}finally{System.out.println("环绕增强---最终增强");}retu resut;}}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!-- 关联Bean Hello --><bean id="hello" class="com.pb.entity.Hello" p:name="张三" p:password="qewr"/><!-- 切入 类 --><bean id="mySchemaAOP" class="com.pb.aop.MySchemaAOP"/><aop:config><!-- 切入点--><aop:pointcut expression="execution(* com.pb.entity.*.*(..))" id="myPoint"/><!--关联切入类、方法和切入点 --><aop:aspect ref="mySchemaAOP"><!-- 切入 前置方法和切入点--><aop:before method="before" pointcut-ref="myPoint"/><!-- 切入 后置方法和切入点--><aop:after method="after" pointcut-ref="myPoint"/><!-- 切入 异常方法和切入点--><aop:after method="myException" pointcut-ref="myPoint"/><!-- 切入 环绕增加方法和切入点--><aop:around method="myAround" pointcut-ref="myPoint"/></aop:aspect></aop:config></beans>
参考:https://www.cnblogs.com/liunanjava/p/4411234.html
https://www.cnblogs.com/boywwj/p/7502185.html
作者:1466028300
来源链接:https://blog.csdn.net/qq_35972907/article/details/95310668
版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。
2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。