Spring AOP
来源:互联网 发布:淘宝网址导航 编辑:程序博客网 时间:2024/06/05 15:05
面向切面编程(Spring AOP)
为了将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,Spring提供了面向切面的编程方式,也称Spring AOP,这有效的减少了系统间的重复代码,达到了模块间的松耦合目的。
AOP,Aspect Oriented Programing,即面向切面编程。AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码,主要体现在事务处理、日志管理、权限控制、异常处理等方面。
目前流行的AOP框架有两个,分别是Spring AOP和AspectJ。AspectJ是一个基于Java语言的AOP框架。
AOP术语
- Joinpoint(连接点):是指那些被拦截到的点,在Spring中,可以被动态代理拦截目标类的方法。
- Pointcut(切入点):是指要对哪些Joinpoint进行拦截,即被拦截的拦截点。
- Advice(通知):是指拦截到Joinpoint之后要做的事情,即对切入点增强的内容。
- Target(目标):是指代理的目标对象。
- Weaving(织入):是指把增强代码应用到目标上,生成代理对象的过程。
- Proxy(代理):是指生成的代理对象。
- Aspect(切面):是切入点和通知的结合。
AspectJ开发
基于XML的声明式AspectJ
导入AOP的的jar包
- spring-aop-3.2.0.RELEASE.jar:是Spring为AOP提供的实现。
- com.springsource.org.aopalliance-1.0.0.jar:是AOP联盟提供的规范。
导入AsprctJ相关的jar包
- spring-aspects-3.2.0.RELEASE.jar:Spring为AspectJ提供的实现。
- com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar:AspectJ提供的规范。
建立UserDao.java
package cn.itcast.dao;public interface UserDao { void save(); void update(); void delete(); void find();}
UserDaoImpl.java
package cn.itcast.dao;public class UserDaoImpl implements UserDao{ @Override public void save() { System.out.println("save添加用户"); } @Override public void update() { System.out.println("update修改用户"); } @Override public void delete() { System.out.println("delete删除用户"); } @Override public void find() { System.out.println("find查询用户"); }}
MyAspect.java
package cn.itcast.aspectj.xml;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;/* * 切面类,在此编写通知 * 可以在XML配置文件中确定通知类型 */public class MyAspect { //前置通知 public void myBefore(JoinPoint joinPoint){ System.out.println("前置通知,目标:"); System.out.println(joinPoint.getTarget()+",方法名称:"); System.out.println(joinPoint.getSignature().getName()); } //后置通知 public void myAfterReturning(JoinPoint joinPoint){ System.out.println("后置通知,方法名称:"+joinPoint.getSignature().getName()); } //环绕通知 //ProceedingJoinPoint是JoinPoint子接口,表示可以执行目标方法 //1.必须返回Object类型值 //2.必须接收一个参数,类型为ProceedingJoinPoint //3.必须throws Throwable public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ //开始 System.out.println("环绕开始"); //执行当前目标方法 Object obj=proceedingJoinPoint.proceed(); //结束 System.out.println("环绕结束"); return obj; } //异常通知 public void myAfterThrowing(JoinPoint joinPoint,Throwable e){ System.out.println("异常通知,出错了"+e.getMessage()); } //最终通知 public void myAfter(){ System.out.println("最终通知"); }}
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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 1.目标类 --> <bean id="userDao" class="cn.itcast.dao.UserDaoImpl"></bean> <!-- 2.切面 --> <bean id="myAspect" class="cn.itcast.aspectj.xml.MyAspect"></bean> <!-- 3.aop编程 --> <aop:config> <aop:aspect ref="myAspect"> <!-- 3.1 配置切入点,通知最后增强哪些方法 --> <aop:pointcut expression="execution(* cn.itcast.dao..*.*(..))" id="myPointCut"/> <!-- 3.2关联通知Advice和切入点pointCut --> <!-- #1前置通知 --> <aop:before method="myBefore" pointcut-ref="myPointCut"/> <!-- #2后置通知,在方法返回之后执行,就可以获得返回值 returning属性:用于设置后置通知的第二个参数的名称,类型是Object --> <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal"/> <!-- #3环绕通知 --> <aop:around method="myAround" pointcut-ref="myPointCut"/> <!-- #4抛出通知:用于处理程序发生异常,就可以接受当前方法产生的异常 注意:如果程序没有异常,将不会执行增强 throwing属性:用于设置通知第二个参数的名称,类型Throwable --> <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/> <!-- #5最终通知:无论程序发生任何事情,都将执行 --> <aop:after method="myAfter" pointcut-ref="myPointCut"/> </aop:aspect> </aop:config></beans>
AspectJ表达式
execution() 用于描述方法
语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
- 修饰符:一般省略。
- public:公共方法
- *:任意
- 返回值:不能省略
- void:无返回值
- String:返回值为字符串
- *:任意(一般用这个)
- 包:可以省略
- com.eaglezsx.crm:固定包
- com.eaglezsx.crm.*.service:crm包下面的任意子包,但要包含service。比如com.eaglezsx.crm.staff.service
- com.eaglezsx.crm..:crm下面的任意子包(包括孙包)
- com.eaglezsx.crm.*.service.. :crm包下面任意子包,固定目录service,service目录任意包
- 类:可以省略
- UserServiceImplement:指定类
- *Impl:以Impl结尾的类
- User*:以User开头的类
- *:任意类
- 方法名:不能省略
- addUser:固定方法
- add*:以add开头的方法
- *Do:以Do结尾的方法
- *:任意方法
- (参数)
- ():无参
- (int):一个整型参数
- (int,int):两个整型参数
- (..):任意参数
- throws:可省略,一般不写。
* cn.itcast.dao..*.*(..)意思是,返回值任意,cn.itcast.dao下的任意包,下的任意类,下的任意方法,方法的参数任意
TestXML.java
package cn.itcast.aspectj.xml;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.itcast.dao.UserDao;public class TestXML { @Test public void demo01(){ String xmlPath="applicationContext.xml"; ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath); //1.从Spring容器获得内容 UserDao userDao=(UserDao)applicationContext.getBean("userDao"); //2.执行方法 userDao.save(); }}
运行结果
前置通知,目标:cn.itcast.dao.UserDaoImpl@110fcd9,方法名称:save环绕开始save添加用户后置通知,方法名称:save环绕结束最终通知
基于Annotation的声明式AspectJ
- @AspectJ:用于定义一个切面
- @Before:用于定义前置通知,相当于BeforeAdvice
- @AfterReturning:用于定义后置通知,相当于AfterReturningAdvice
- @Around:用于定义环绕通知,相当于MethodInterceptor
- @AfterThrowing:用于定义抛出通知,相当于ThrowAdvice
- @After:用于定义最终final通知,不管是否异常,该通知都会执行
@Aspect@Componentpublic class MyAspect { /* 用于取代<aop:pointcut expression="execution(* cn.itcast.dao..*.*(..))" id="myPointCut"/> 要求:方法必须是private没有值 名称自定义,没有参数 */ @Pointcut("execution(* cn.itcast.dao..*.*(..))") private void myPointCut(){} @Before("myPointCut()") public void myBefore(JoinPoint joinPoint){ ... } @AfterReturning(value="myPointCut()") public void myAfterReturning(JoinPoint joinPoint){ ... } @Around("myPointCut()") public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ ... } @AfterThrowing(value="myPointCut()",throwing="e") public void myAfterThrowing(JoinPoint joinPoint,Throwable e){ ... } @After("myPointCut()") public void myAfter(){ ... }}
@Repository("userDao")public class UserDaoImpl implements UserDao{ ...}
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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 扫描包:使注解生效 --> <context:component-scan base-package="cn.itcast"></context:component-scan> <!-- 使切面开启自动代理 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
TestAnnotation.java
public class TestAnnotation { @Test public void demo01(){ String xmlPath="applicationContext.xml"; ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath); //1.从Spring容器获得内容 UserDao userDao=(UserDao)applicationContext.getBean("userDao"); //2.执行方法 userDao.save(); }}
阅读全文
0 0
- 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
- maven执行ssh三大框架+oracle数据库的一般步骤及注意事项
- 各排序算法时间复杂度和空间复杂度对比总结
- scrapy无法存入数据
- CSS页面布局技巧(二)
- C语言基础之scanf的问题
- Spring AOP
- 奇偶分割数组
- Java探秘之神秘的字符串String(二)
- 优秀的API接口设计原则及方法
- 【JSP】jsp的组成
- Mybatis中的#{} 和 ${}
- MATLAB变量
- Paper阅读
- 大数的四则运算 【模版】