Spring---AOP面向切面编程
来源:互联网 发布:软件生命周期 编辑:程序博客网 时间:2024/05/16 02:26
我查阅了一些资料 aop还是有些难以理解的,oop面向对象编程,aop是oop的一个完善,oop定义了了程序从上到下的关系,而aop定义了程序左右关系,oop中如果想给分散的对象引入一个公共的功能,例如日志功能,日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。这种散布在各处的与核心功能无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
而aop它使用了一种“横切”技术,把程序横向切开,并且将影响了多个类的公共行为封装起来,变成一个可重用的模块,并将其命名为“Aspect“ 这样就不会重复造轮子,减少了代码的重复,降低了模块之间的耦合度,并且有利于后期的维护
AOP的相关概念:
1.关注点:增加的是什么功能,如日志,安全等 2.切面:aspect一个关注点的模块化,这个关注点实现可能另外横切多个对象 3.通知:在切面某个特定的连接点上执行的动作 4.织入:把切面连接到其他应用程序类型或对象上,并创建一个被通知的对象
四种通知类型
第一种 前置通知
实现一个接口MethodBeforeAdvice
public class BeforeAdvice implements MethodBeforeAdvice{ /** * method:被调用的 方法对象 * args:参数列表 * target:目标对象 */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("前置通知"); }}
第二种后置通知
实现的接口:AfterReturningAdvice
public class AfterAdvice implements AfterReturningAdvice{ /** * values:返回值 * method:要执行的方法对象 * args:参数列表 * target:目标对象 */ @Override public void afterReturning(Object values, Method method, Object[] args, Object target) throws Throwable { System.out.println("后置通知"); }}
第三种异常通知
实现的接口是ThrowsAdvice
public class ExceptionAdvice implements ThrowsAdvice{ /** * method:被调用的 方法对象 * args:参数列表 * target:目标对象 * Exception:异常类型 */ public void afterThrowing(Method method, Object[] args, Object target, Exception e){ System.out.println("方法 " + method.getName() + " 异常出现 : " + e.getClass().getName()); } public void afterThrowing(Throwable e){ System.out.println("异常出现 : " + e.getClass().getName()); }}
第四种环绕通知,环绕通知是上面三种通知的结合体,我们可以二选一,写了上面三个通知就不用使用环绕通知,当然我们也可以只写一个环绕通知
public class AroundAdvice implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { Object obj = null; System.out.println("环绕通知"); try { // 前置通知 System.out.println("前置通知"+invocation.getMethod().getName()); // 调用具体方法 obj = invocation.proceed(); // 后置通知 System.out.println("后置通知"+invocation.getMethod().getName()); } catch (Exception e) { // 异常通知 e.printStackTrace(); System.out.println("异常通知" + e.getClass().getName()); throw e; } return obj; }}
下面是beans.xml的配置 (两种方式)
第一种方式 AspectJ方式(直接在下配置)
<?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" > <bean id="service" class="cn.bjsxt.service.impl.UserServiceImpl"></bean> <bean id="before" class="cn.bjsxt.avice.BeforeAdvice"></bean> <bean id="after" class="cn.bjsxt.avice.AfterAdvice"></bean> <bean id="e" class="cn.bjsxt.avice.ExceptionAdvice"></bean> <bean id="around" class="cn.bjsxt.avice.AroundAdvice"></bean> <aop:config> <!-- expression:代表在什么情况下执行advice功能,属性值为一个表达式 execution代表执行 * cn.bjsxt.service.impl.*.*(..) 第一个*代表所有返回类型 cn.bjsxt.service.impl代表需要执行advice功能的包 第二个*代表包中所有的类 第三个*代表类中所有的方法 (..)代表任意参数结构 --><aop:pointcut expression="execution(* cn.bjsxt.service.impl.*.*(..))" id="pointcut"/><!-- advice-ref:通知对象的引用,pointcut-ref:切入点对象的引用 --> <aop:advisor advice-ref="before" pointcut-ref="pointcut"/> <aop:advisor advice-ref="after" pointcut-ref="pointcut"/> <aop:advisor advice-ref="e" pointcut-ref="pointcut"/> <aop:advisor advice-ref="around" pointcut-ref="pointcut"/> </aop:config></beans>
上面我把前置通知,后置通知注释了,因为同时配置这三个通知会产生干扰,所以执行的时候看一下,需要执行什么。
第二种配置方式 :POJO方式(在下配置)
首先创建一个Logs类
public class Logs { public void before(){ System.out.println("前置通知"); } public void after(){ System.out.println("后置通知"); } public void around(){ System.out.println("环绕通知"); }}
配置:配置时注意顺序,后置通知如果配置在前置通知前将不会执行
<!-- 配置srvice --> <bean id="userService" class="cn.bjsxt.service.impl.UserServiceImpl"/> <!-- 基于pojo配置 --> <bean id="logs" class="cn.bjsxt.avdvice.Logs"/> <aop:config> <!--引用pojo --> <aop:aspect ref="logs"> <aop:pointcut expression="execution( * cn.bjsxt.service.impl.*.*(..))" id="aspect"/> <aop:before method="before" pointcut-ref="aspect"/> <aop:after method="after" pointcut-ref="aspect"/> <aop:around method="around" pointcut-ref="aspect"/> </aop:aspect> </aop:config>
还有一种是注解形式,不需要配置<aop:config>
就可以使用,直接创建一个切入的类,和一个引入的类
使用注解时记住在类前加入@Aspect,否则不会执行通知,
@Aspectpublic class Loggs { //配置切入点 @Before("execution ( * cn.bjsxt.service.impl.*.*(..))") public void before(){ System.out.println("方法执行前"); } @After("execution ( * cn.bjsxt.service.impl.*.*(..))") public void after(){ System.out.println("方法执行后"); } @Around("execution ( * cn.bjsxt.service.impl.*.*(..))") public Object aroud(ProceedingJoinPoint jp ) throws Throwable{ System.out.println("环绕前"); System.out.println("签名:"+jp.getSignature()); Object obj = jp.proceed(); System.out.println("环绕后"); return obj; }}
注解的配置
<!-- 配置自定义注解方式 --> <!-- 配置srvice --> <bean id="userService" class="cn.bjsxt.service.impl.UserServiceImpl"/><bean id="loggs" class="cn.bjsxt.log.Loggs"></bean><aop:aspectj-autoproxy/>
补充:expression=”execution( * cn.bjsxt.service.impl.* .* (..))”,这个属性值中的 * 类似正则中的 * ,是全部的意思,也可以写为print* ,这代表切面中只要是以print开头的方法都会拦截到
以上是个人的认识,不足之处请之处,欢迎补充 互相学习 谢谢
- 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)
- Spring---AOP面向切面编程
- Spring面向切面编程AOP
- Spring:Aop面向切面编程
- tree命令安装
- (四) Java多线程详解之线程池的使用
- BZOJ1911 [Apio2010]特别行动队 斜率优化
- Unity学习(十三)场景优化之四叉树
- 文章标题
- Spring---AOP面向切面编程
- hibernate QBC 查询
- windows下安装mysql用Navicat连接报错
- 去除注册的事件 c# winform
- ListView and Sqlite Database
- 冒泡排序
- java --- Xml数据解析
- IE兼容
- O