北京网站页面设计,电子商务目前就业形势,网站建设的商业目的,中国建设手机银行网站文章目录 初步实现通知执行顺序 各个通知获取细节信息重用切点表达式切点表达式语法细节环绕增强切面的优先级没有接口的情况基于XML的AOP[了解] 初步实现
先导入Spring和Junit4的依赖 dependencygroupIdorg.springframework/groupIdartifactIddependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.11.RELEASE/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion5.2.11.RELEASE/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency导入AOP的依赖 dependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion5.2.11.RELEASE/version/dependency在Spring的配置文件中开启包扫描和AOP注解
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsdcontext:component-scan base-packagecom.iflytek/context:component-scan!-- 开启基于注解的AOP功能 --aop:aspectj-autoproxy/aop:aspectj-autoproxy
/beans也可以通过配置类开启
Configuration
ComponentScan(basePackages com.iflytek)
EnableAspectJAutoProxy
public class MyConfig {
}
创建接口
public interface Calculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j);}创建实现类实现这个接口:
Component
public class CalculatorPureImpl implements Calculator{Overridepublic int add(int i, int j) {int result i j;System.out.println(方法内部 result result);return result;}Overridepublic int sub(int i, int j) {int result i - j;System.out.println(方法内部 result result);return result;}Overridepublic int mul(int i, int j) {int result i * j;System.out.println(方法内部 result result);return result;}Overridepublic int div(int i, int j) {int result i / j;System.out.println(方法内部 result result);return result;}
}
定义切面类
/*** 切面类*/
// Aspect表示这个类是一个切面类
Aspect
// Component注解保证这个切面类能够放入IOC容器
Component
public class LogAspect {// Before注解声明当前方法是前置通知方法// value属性指定切入点表达式由切入点表达式控制当前通知方法要作用在哪一个目标方法上Before(value execution(public int com.iflytek.Calculator.add(int,int)))public void printLogBeforeCore() {System.out.println([AOP前置通知] 方法开始了);}AfterReturning(value execution(public int com.iflytek.Calculator.add(int,int)))public void printLogAfterSuccess() {System.out.println([AOP返回通知] 方法成功返回了);}AfterThrowing(value execution(public int com.iflytek.Calculator.add(int,int)))public void printLogAfterException() {System.out.println([AOP异常通知] 方法抛异常了);}After(value execution(public int com.iflytek.Calculator.add(int,int)))public void printLogFinallyEnd() {System.out.println([AOP后置通知] 方法最终结束了);}}测试
RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(classpath:ApplicationContext.xml)
public class testClass {Autowiredprivate Calculator calculator;//这里一定要导入接口而非实现类Testpublic void test01(){calculator.add(1,2);}
}
运行结果 [AOP前置通知] 方法开始了 方法内部 result 3 [AOP返回通知] 方法成功返回了 [AOP后置通知] 方法最终结束了 通知执行顺序
Spring版本5.3.x以前 前置通知Before目标操作后置通知After返回通知或异常通知AfterReturing/AfterThrowing Spring版本5.3.x以后 前置通知Before目标操作返回通知或异常通知AfterReturing/AfterThrowing后置通知After
各个通知获取细节信息
JoinPoint接口 org.aspectj.lang.JoinPoint
要点1JoinPoint接口通过getSignature()方法获取目标方法的签名要点2通过目标方法签名对象获取方法名要点3通过JoinPoint对象获取外界调用目标方法时传入的实参列表组成的数组
在切面类中
Aspect
// Component注解保证这个切面类能够放入IOC容器
Component
public class LogAspect {// Before注解声明当前方法是前置通知方法// value属性指定切入点表达式由切入点表达式控制当前通知方法要作用在哪一个目标方法上Before(value execution(public int com.iflytek.Calculator.add(int,int)))public void printLogBeforeCore(JoinPoint joinPoint) {Signature signature joinPoint.getSignature();//方法名addSystem.out.println(methodNamesignature.getName());//获取目标方法声明类型(public、private、protected) 1025System.out.println(modifierssignature.getModifiers());// 获取目标方法所属类的类名 com.iflytek.CalculatorSystem.out.println(declaringTypeNamesignature.getDeclaringTypeName());Object[] args joinPoint.getArgs();ListObject list Arrays.asList(args);System.out.println(参数);//1,2list.forEach(item-{System.out.println(item);});System.out.println([AOP前置通知] 方法开始了);}AfterReturning(value execution(public int com.iflytek.Calculator.add(int,int)),returning result)//returning 获取方法返回值public void printLogAfterSuccess(Integer result) {System.out.println([AOP返回通知] 方法成功返回了,返回值为result);}AfterThrowing(value execution(public int com.iflytek.Calculator.add(int,int)),throwing throwable)//throwing 获取异常信息public void printLogAfterException(Throwable throwable) {System.out.println([AOP异常通知] 方法抛异常了throwable.getClass().getName());}After(value execution(public int com.iflytek.Calculator.add(int,int)))public void printLogFinallyEnd() {System.out.println([AOP后置通知] 方法最终结束了);}}重用切点表达式
1、在切面类中声明 //定义切点Pointcut(value execution(public int com.iflytek.Calculator.add(int,int)))public void pointCut(){}2、同一个类内部引用 Before(value pointCut())public void printLogBeforeCoreOperation(JoinPoint joinPoint) {3、在不同类中引用 该方法在LogAspect2类中 Before(value com.iflytek.LogAspect.pointCut())public Object roundAdvice(ProceedingJoinPoint joinPoint) {}4、集中管理 而作为存放切入点表达式的类可以把整个项目中所有切入点表达式全部集中过来便于统一管理
Component
public class PointCuts {Pointcut(value execution(public int *..Calculator.sub(int,int)))public void globalPointCut(){}Pointcut(value execution(public int *..Calculator.add(int,int)))public void secondPointCut(){}Pointcut(value execution(* *..*Service.*(..)))public void transactionPointCut(){}
}切点表达式语法细节
用开头的*号代替“权限修饰符”和“返回值”部分表示“权限修饰符”和“返回值”不限在包名的部分一个“*”号只能代表包的层次结构中的一层表示这一层是任意的。 例如*.Hello匹配com.Hello不匹配com.iflytek.Hello 在包名的部分使用“*…”表示包名任意、包的层次深度任意在类名的部分类名部分整体用*号代替表示类名任意在类名的部分可以使用*号代替类名的一部分
*Service上面例子表示匹配所有名称以Service结尾的类或接口
在方法名部分可以使用*号表示方法名任意在方法名部分可以使用*号代替方法名的一部分
*Operation上面例子表示匹配所有方法名以Operation结尾的方法
在方法参数列表部分使用(…)表示参数列表任意在方法参数列表部分使用(int,…)表示参数列表以一个int类型的参数开头在方法参数列表部分基本数据类型和对应的包装类型是不一样的 切入点表达式中使用 int 和实际方法中 Integer 是不匹配的 在方法返回值部分如果想要明确指定一个返回值类型那么必须同时写明权限修饰符
execution(public int *..*Service.*(.., int))上面例子是对的下面例子是错的
execution(* int *..*Service.*(.., int))但是public *表示权限修饰符明确返回值任意是可以的。
* void 就是错误的对于execution()表达式整体可以使用三个逻辑运算符号 execution() || execution()表示满足两个execution()中的任何一个即可execution() execution()表示两个execution()表达式必须都满足!execution()表示不满足表达式的其他方法
环绕增强
环绕通知对应整个try…catch…finally结构包括前面四种通知的所有功能。 //定义切点Pointcut(value execution(public int com.iflytek.Calculator.add(int,int)))public void pointCut(){}Around(value pointCut())public void printAround(ProceedingJoinPoint joinPoint){try {//此处相当于前置增强System.out.println(before...);joinPoint.proceed(joinPoint.getArgs());System.out.println(afterReturning...);} catch (Throwable e) {
// throw new RuntimeException(e);e.printStackTrace();System.out.println(afterThrowing);}finally {//此处相当于后置增强System.out.println(after...);}}切面的优先级
相同目标方法上同时存在多个切面时切面的优先级控制切面的内外嵌套顺序。
优先级高的切面外面优先级低的切面里面 eg如果 是Before前置增强则优先级高的先执行
如果是After后置增强则优先级低的先执行
使用Order注解可以控制切面的优先级
Order(较小的数)优先级高Order(较大的数)优先级低
没有接口的情况
在目标类没有实现任何接口的情况下Spring会自动使用cglib技术实现代理
基于XML的AOP[了解]
将之前用到的AOP的注解都删除 使用xml配置 bean idaspect classcom.iflytek.LogAspect/beanbean idcalculatorPure classcom.iflytek.CalculatorPureImpl/beanaop:config
!-- 定义切入点和规则--aop:pointcut idpc expressionexecution(public Integer com.iflytek.Calculator.add(int ,int))/
!--切面--aop:aspect refaspectaop:before methodprintLogBeforeCore pointcut-refpc/aop:beforeaop:after-returning methodprintLogAfterSuccess pointcut-refpc returningresult/aop:after-returningaop:after-throwing methodprintLogAfterException pointcut-refpc throwingthrowable/aop:after-throwingaop:after methodprintLogFinallyEnd pointcut-refpc/aop:after/aop:aspect/aop:config