Spring-AOP
来源:互联网 发布:塔吊桩基础计算软件 编辑:程序博客网 时间:2024/06/15 10:07
一. AOP术语
横切关注点: 对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
切面(aspect): 类是对物体特征的抽象,切面就是对横切关注点的抽象。
通知(advice): 切面拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
目标(target): 被代理(通知)的对象。
代理(proxy): 代理对象。向目标对象应用通知之后创建的对象。
连接点(joinpoint):是切面类和业务类的连接点,其实就是封装了业务方法的一些基本属性,作为通知的参数来解析。
切点(pointcut):业务类中指定的方法,作为切面切入的点。其实就是指定某个方法作为切面切的地方。相当于查询条件,在哪些业务方法中需要加入通知,spring自动生成新的代理对象。
通知:
前置通知:在切入点之前执行。
后置通知:在切入点执行完成后,执行通知。
返回通知: 返回通知, 在方法返回结果之后执行。
环绕通知(around advice):包围切入点,调用方法前后完成自定义行为。
异常通知(after throwing advice):在切入点抛出异常后,执行通知。
二. AspectJ注解
在 AspectJ 注解中,
切面只是一个带有 @Aspect 注解的 Java 类。
通知是标注有某种注解的简单的 Java 方法。
AspectJ 支持 5 种类型的通知注解:
* @Before: 前置通知, 在方法执行之前执行。
* @After: 后置通知, 在方法执行之后执行。
* @AfterRunning: 返回通知, 在方法返回结果之后执行。
* @AfterThrowing: 异常通知, 在方法抛出异常之后。
* @Around: 环绕通知, 围绕着方法执行。
三. 导入Spring AOP jar包
使用maven pom.xml导入依赖jar。
<properties> <spring.version>4.3.8.RELEASE</spring.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency><dependencies>
四.启用AspjectJ注解
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!--自动扫描--> <context:component-scan base-package="com.cd.aop.impl"></context:component-scan> <!-- 启用AspjectJ 注解: 自动为匹配的类生成代理对象 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>
五.前置、后置、 返回、异常通知
Calculator.java
package com.cd.spring.bean;public interface Calculator { public int add(int num1, int num2); public int div(int num1, int num2);}
CalculatorImpl.java
package com.cd.spring.bean;import org.springframework.stereotype.Component;@Componentpublic class CalculatorImpl implements Calculator{ public int add(int num1, int num2){ System.out.println("Calculator add..."); return num1 + num2; } public int div(int num1, int num2){ System.out.println("Calculator div..."); return num1 / num2; }}
切面类
CalculatorAspect.java
package com.cd.spring.bean;import java.util.Arrays;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;// 使用注解@Aspect声明一个切面类@Aspect@Componentpublic class CalculatorAspect { // 通知 @Before(value="execution(* com.cd.spring.bean.*(..))") public void beforeMethod(JoinPoint jp){ // JoinPoint切入点 String methodName = jp.getSignature().getName(); System.out.println(methodName); System.out.println("before method execute,args are "+Arrays.toString(jp.getArgs())); } @After("execution(* com.cd.spring.bean.*(..))") public void afterMethod(JoinPoint jp){ System.out.println("after method execute,args are "+Arrays.toString(jp.getArgs())); } @AfterThrowing(value="execution(* com.cd.spring.bean.*(..))",throwing="ex") public void afterThrow(Exception ex){ System.out.println("afterThrow"+ex.getMessage()); } @AfterReturning(value="execution(* com.cd.spring.bean.*(..))",returning="result") public void afterReturn(Object result){ System.out.println("the result is "+result); }}
调用:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Calculator calc = (Calculator) context.getBean("calculatorImpl");calc.add(50, 50); // calc.div(100, 0); // 异常通知
调用结果:
add
before method execute,args are [50, 50]
Calculator add…
after method execute,args are [50, 50]
the result is 100
div
before method execute,args are [100, 0]
after method execute,args are [100, 0]
afterThrow/ by zero
六. 环绕通知
package com.cd.spring.bean;import java.util.Arrays;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;@Aspect@Componentpublic class CalculatorAspectAround { @Around(value="execution(* execution(* com.cd.spring.bean.*(..))") public Object aroundMethod(ProceedingJoinPoint pjp){ Object result = null; String methodName = pjp.getSignature().getName(); try { System.out.println(methodName + "前置通知...); result = jointPoint.proceed(); System.out.println(methodName + "后置通知..."); } catch (Throwable e) { System.out.println(methodName + "异常通知..."); throw new RuntimeException(e); } System.out.println(methodName + "返回通知....."); return result; }}
注意:@Around环绕通知,必须携带对象ProceedingJoinPoint参数
环绕通知类似于动态代理的全部过程,可以决定是否执行目标方法
七. 指定切面的优先级
在同一个连接点上应用不止一个切面时, 除非明确指定, 否则它们的优先级是不确定的.
切面的优先级可以通过实现 Ordered 接口或利用 @Order 注解指定。
使用@Order注解,值越小,优先级越高。
@Order(1)@Aspect@Componentpublic class LoggingAspect {}
八. 重用切入点定义
在 AspectJ 切面中, 可以通过 @Pointcut注解将一个切入点声明成简单的方法。切入点的方法体通常是空的。
切入点方法的访问控制符同时也控制着这个切入点的可见性。
如果切入点要在多个切面中共用, 最好将它们集中在一个公共的类中. 在这种情况下, 它们必须被声明为 public。 在引入这个切入点时, 必须将类名也包括在内。 如果类没有与这个切面放在同一个包中, 还必须包含包名。
其他通知可以通过方法名称引入该切入点。
CalculatorAspect.java
package com.cd.spring.bean;import java.util.Arrays;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;// 使用注解@Aspect声明一个切面类@Aspect@Componentpublic class CalculatorAspect { /** * 定义一个方法, 用于声明切入点表达式。 * 使用 @Pointcut 来声明切入点表达式。 */ @Pointcut("execution(public int com.cd.spring.bean.*(..))") public void declareJointPointExpression(){} // 通知 @Before(value="declareJointPointExpression()") public void beforeMethod(JoinPoint jp){ // JoinPoint切入点 String methodName = jp.getSignature().getName(); System.out.println(methodName); System.out.println("before method execute,args are "+Arrays.toString(jp.getArgs())); } @After("com.cd.spring.bean.CalculatorAspect.declareJointPointExpression()") public void afterMethod(JoinPoint jp){ System.out.println("after method execute,args are "+Arrays.toString(jp.getArgs())); } @AfterThrowing(value="declareJointPointExpression()",throwing="ex") public void afterThrow(Exception ex){ System.out.println("afterThrow"+ex.getMessage()); } @AfterReturning(value="declareJointPointExpression()",returning="result") public void afterReturn(Object result){ System.out.println("the result is "+result); }}
九. 基于xml配置切面
将Calculator、CalculatorImpl、CalculatorAspect类移到其他包里面,去掉类以及方法中的所有注解。
定义新的配置文件applicationContext-xml.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <!-- 配置业务bean --> <bean id="calculator" class="com.cd.spring.xml.CalculatorImpl"></bean> <!-- 配置切面bean --> <bean id="calculatorAspect" class="com.cd.spring.xml.CalculatorAspect"></bean> <!-- 配置AOP --> <aop:config> <!--配置切点表达式--> <aop:pointcut expression="execution(* com.cd.spring.xml.Calculator.*(int,int))" id="pointCut" /> <!--配置切面及通知--> <aop:aspect ref="calculatorAspect" order="1"> <aop:before method="beforeMethod" pointcut-ref="pointCut" /> <aop:after method="afterMethod" pointcut-ref="pointcut"/> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/> </aop:aspect> </aop:config></beans>
- AOP、Spring的AOP
- AOP--Spring AOP
- Spring AOP 嵌套AOP
- spring AOP
- Spring AOP
- Spring AOP
- spring aop
- Spring AOP
- spring AOP
- spring aop
- Spring aop
- Spring-AOP
- Spring AOP
- spring aop
- spring aop
- Spring AOP
- Spring AOP
- Spring Aop
- 百度地图根据地点获取经纬度
- Socket详解
- struts2学习--注解开发
- 新增记录到TRIP数据库(JAVA)
- Myeclipse添加Mysql数据库时出现“Unable to create connection .Check your URL”
- Spring-AOP
- IT牛们的bat面试心得与经验总结
- bzoj2301
- 线程
- CS Academy Round #32 Light Count
- 推荐一款调试法宝--虚拟示波器
- CentOS7安装EPEL源
- Toggle+Switch
- 模拟CMOS集成电路设计 学习笔记(一)