随笔录 之 spring 自学杂记(四) -- AOP(二)
2016-12-16 16:37
579 查看
Spring AOP
spring AOP(面向方面编程)框架,用于在模块化方面的横切关注点。简单得说,它只是一个拦截器拦截一些过程,在方法执行之前或之后添加额外的功能。
基于xml配置文件的管理方式:使用spring配置文件定义切面及切点。
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd ">
AOP术语
1、切面(Aspect)
描述的一个应用系统的一个方面或者领域,如:日志、权限、事务等。2、连接点(JoinPoint)
连接点是应用程序执行过程中插入切面的点,这些点可以是一个方法的调用、异常的抛出等。3、通知(advise)
通知它是切面的具体实现,它表示切面的行为。定义了切面是什么、如何使用等,描述了切面要实现的工作。
spring支持五种类型的通知:
Before(前) : org.apringframework.aop.MethodBeforeAdvice
After-returning(返回后) : org.springframework.aop.AfterReturningAdvice
After-throwing(抛出后) : org.springframework.aop.ThrowsAdvice
Arround(周围) : org.aopaliance.intercept.MethodInterceptor
Introduction(引入) : org.springframework.aop.IntroductionInterceptor
一个简单实例
定义切面:package com.wm.spring.AOP.Aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class DefaultAspect { // 前置通知 public void doBefore(JoinPoint jp) { System.out.println("method before 。。。"); System.out.println("method name: "+jp.getTarget().getClass().getName() + " - "+jp.getSignature().getName()); } // 返回后通知 public void doAfter(JoinPoint jp) { System.out.println("method name: "+jp.getTarget().getClass().getName() + " - "+jp.getSignature().getName()); System.out.println("method after 。。。"); } // 环绕通知 public void doAround(ProceedingJoinPoint jp) throws Throwable { System.out.println(" before ...."); jp.proceed(); System.out.println(" method name: "+jp.getTarget().getClass().getName() + " - "+jp.getSignature().getName()); System.out.println(" after ...."); } // 抛出异常后通知 public void doThrow(Throwable e){ System.out.println("after throw ..... "+e); } }
JoinPoint 里包含了如下几个常用方法:
Object[] getArgs(): 返回执行目标方法时的参数。
Signature getSignature(): 返回被增强的方法的相关信息。
Object getTarget(): 返回被织入增强处理的目标对象。
Object getThis(): 返回 AOP 框架为目标对象生成的代理对象。
基于xml配置管理方式
<aop:config> <aop:aspect id="myAspect" ref="defaultAspect"> <aop:pointcut expression="execution(* com.wm.spring.IOC.*.*(..))" id="myPoincut"/> <!-- 前置通知 --> <aop:before method="doBefore" pointcut-ref="myPoincut"/> <!-- 返回后通知 --> <aop:after-returning method="doAfter" pointcut-ref="myPoincut"/> <!-- 环绕通知 --> <aop:around method="doAround" pointcut-ref="myPoincut"/> <!-- 抛出异常后通知 --> <aop:after-throwing method="doThrow" pointcut-ref="myPoincut" throwing="e"/> </aop:aspect> </aop:config> <bean id="defaultAspect" class="com.wm.spring.AOP.Aspect.DefaultAspect"></bean> <bean id="people" class="com.wm.spring.IOC.People"> <property name="name" value="Tom" /> <property name="age" value="19"></property> </bean>
抛出异常后通知中,< aop:after-throwing />要在通知中获取 异常,就必须配置属性 throwing=”e”,这样就可以获取到,不然会报错的。
目标对象:
package com.wm.spring.IOC; public class People { private String name; private int age; public void eat(){ System.out.println(name+ " 正在吃饭。。。。。。"); } public void sleep(){ System.out.println(name + " 正在睡觉。。。。。"); } public void doErrorThing() { throw new IllegalArgumentException("做错事。。。。。"); } @Override public String toString() { return String.format("姓名:%s <-> 年龄:%d", name,age); } 。。。。。。 setting and getting }
测试及结果:
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.wm.spring.IOC.People; public class AOPTest { private ApplicationContext ac ; @Before public void init(){ ac = new ClassPathXmlApplicationContext("ApplicationContext.xml"); } @Test public void doTestAOP(){ People pp = (People)ac.getBean("people"); pp.eat(); pp.sleep(); pp.doErrorThing(); } }
运行结果:
信息: Loading XML bean definitions from class path resource [ApplicationContext.xml] method before 。。。 method name: com.wm.spring.IOC.People - eat before .... Tom 正在吃饭。。。。。。 method name: com.wm.spring.IOC.People - eat after .... method name: com.wm.spring.IOC.People - eat method after 。。。 method before 。。。 method name: com.wm.spring.IOC.People - sleep before .... Tom 正在睡觉。。。。。 method name: com.wm.spring.IOC.People - sleep after .... method name: com.wm.spring.IOC.People - sleep method after 。。。 method before 。。。 method name: com.wm.spring.IOC.People - doErrorThing before .... after throw ..... java.lang.IllegalArgumentException: 做错事。。。。。
额外的配置
maven pom.xml需要引入:
aspectjrt.jar
aspectjweaver.jar
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.6</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.6</version> </dependency>
基于注解的方式(使用Aspectj)
一个小例子:定义一个切面:
package com.wm.spring.AOP.Aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Order(1) // order 可以定义切面的优先级 ---> 越小越优先 @Aspect // 声明切面 @Component // bean 注册到容器中去 public class BaseOnAnnotationAspect { // 前置通知 @Before("execution(* com.wm.spring.IOC.People.*(..))") public void doBefore(JoinPoint jp) { System.out.println("method before 。。。"); System.out.println("method name: "+jp.getTarget().getClass().getName() + " - "+jp.getSignature().getName()); } // 返回后通知 @AfterReturning(value = "execution(* com.wm.spring.IOC.People.*(..))") public void doAfterReturning(JoinPoint jp) { System.out.println("method name: "+jp.getTarget().getClass().getName() + " - "+jp.getSignature().getName()); System.out.println("method after returning 。。。"); } // 后置通知 //出现异常一样的返回 @After(value = "execution(* com.wm.spring.IOC.People.*(..))") public void doAfter(JoinPoint jp) { System.out.println(jp.getTarget().getClass().getSuperclass()); System.out.println("method name: "+jp.getTarget().getClass().getName() + " - "+jp.getSignature().getName()); System.out.println("method after 。。。"); } // 环绕通知 @Around(value = "execution(* com.wm.spring.IOC.People.*(..))") public void doAround(ProceedingJoinPoint jp) throws Throwable { System.out.println(" before ...."); jp.proceed(); System.out.println(" method name: "+jp.getTarget().getClass().getName() + " - "+jp.getSignature().getName()); System.out.println(" after ...."); } // 抛出异常后通知 @AfterThrowing(throwing = "e" , value = "execution(* com.wm.spring.IOC.People.*(..))") public void doThrow(Throwable e){ System.out.println("after throw ..... "+e); } }
其中
注解:@Order 可以在多个切面中实现优先级,优先级越高,order值越小。
注解:@Pointcut 可以定义一个切点的方法:
@Pointcut("execution(* com.wm.spring.IOC.People.*(..))") // 定义的切点 public void definePointCut(){} // 方法体内 不要写内容 // 前置通知 @Before("definePointCut()") // 使用定义的切点方法 实现切点 public void doBefore(JoinPoint jp) { System.out.println("method before 。。。"); System.out.println("method name: "+jp.getTarget().getClass().getName() + " - "+jp.getSignature().getName()); }
配置文件:
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd ">
<!-- 自动扫描 切面 所在的包 -->
<context:component-scan base-package="com.wm.spring.AOP.Aspect"></context:component-scan>
<!-- 使用注解方式的 ,这个必须加, 是自动实现代理模式 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
必须要引用AOP的命名空间和约束,才能使用
相关文章推荐
- MyEclipse中代码格式化后自动换行
- springMVC整合swagger(亲自试验完全可用)
- 建立Meaven项目(Meaven+SpringMvc)
- 基于java使用JavaMail发送邮件
- java基础--27.了解线程组ThreadGroup
- Eclipse 导入Code Template模板
- nested exception is java.lang.IllegalArgumentException: Parameter with that position [1] did not exi
- Spark编程指南入门之Java篇一-基本知识
- Mac 中eclipse 遇到的问题及简单设置
- Java概述
- eclipse javadoc帮助文档生成
- Core java 第九版第三章基本程序结构
- 小博老师解析Java核心技术 ——JSwing文本型控件
- SpringMVC 读取配置文件
- 随笔记---java
- Java利用System.getProperty("file.encoding")获取编码分析
- java Annotation的使用和分析
- 非注解和注解的处理器映射器和适配器---SpringMVC学习笔记(三)
- Java:按值传递还是按引用传递详细解说
- Java 定时任务