什么是AOP

AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

AOP使用场景

AOP用来封装横切关注点,具体可以在下面的场景中使用:

Authentication 权限

Caching 缓存

Context passing 内容传递

Error handling 错误处理

Lazy loading 懒加载

Debugging  调试

logging, tracing, profiling and monitoring 记录跟踪 优化 校准

Performance optimization 性能优化

Persistence  持久化

Resource pooling 资源池

Synchronization 同步

Transactions 事务

Spring AOP底层技术

Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。

动态代理利用反射的原理,给对象动态的生产代理对象,在执行的方法前后来执行相关内容:

/**
* 动态代理类
*
* @author yanbin
*
*/ public class DynamicProxy implements InvocationHandler { /** 需要代理的目标类 */
private Object target;
/**
* 写法固定,aop专用:绑定委托对象并返回一个代理类
*
* @param delegate
* @return
*/ public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
} /**
* @param Object
* target:指被代理的对象。
* @param Method
* method:要调用的方法
* @param Object
* [] args:方法调用时所需要的参数
*/ @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
// 切面之前执行
System.out.println("切面之前执行");
// 执行业务
result = method.invoke(target, args);
// 切面之后执行
System.out.println("切面之后执行");
return result;
}
}

CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。采用的是继承的方式

/**
* 使用cglib动态代理
*
* @author yanbin
*
*/ public class CglibProxy implements MethodInterceptor { private Object target; /**
* 创建代理对象
*
* @param target
* @return
*/ public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
} @Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object result = null;
System.out.println("事物开始");
result = methodProxy.invokeSuper(proxy, args);
System.out.println("事物结束");
return result;
}
}

AOP相关概念

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。

连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice

切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上

引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口

目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO

AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

几种实现方式

1、基于代理的AOP

2、纯简单java对象切面

3、@Aspect注解形式的

4、注入形式的Aspcet切面

面先写一下几个基本的类。

接口类:

/**
* 定义一个接口
* @author 陈丽娜
* @version 2015年5月31日上午9:16:50
*/ public interface Sleepable { /**
* 睡觉方法
* @author 陈丽娜
* @version 2015年5月31日上午9:17:14
*/ void sleep(); }

实现类:

/**
* 陈丽娜 本人实现睡觉接口
* @author 陈丽娜
* @version 2015年5月31日下午4:51:43
*/ public class ChenLliNa implements Sleepable { @Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("乖,该睡觉了!");
}
}

增强类:

/**
* 定义一个睡眠的增强 同时实现前置 和后置
* @author 陈丽娜
* @version 2015年5月31日上午9:24:43
*/ public class SleepHelper implements MethodBeforeAdvice, AfterReturningAdvice { @Override
public void afterReturning(Object returnValue, Method method,Object[] args, Object target) throws Throwable {
System.out.println("睡觉前要敷面膜");
} @Override
public void before(Method method, Object[] args, Object target)throws Throwable {
System.out.println("睡觉后要做美梦");
}
}

1、基于代理的AOP

<!-- 创建一个增强 advice -->

       <bean id ="sleepHelper" class="com.tgb.springaop.aspect.SleepHelper"/>
<bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/>
<!-- 定义切点 匹配所有的sleep方法-->
<bean id ="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*sleep"></property>
</bean> <!-- 切面 增强+切点结合 -->
<bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="sleepHelper"/>
<property name="pointcut" ref="sleepPointcut"/>
</bean> <!-- 定义代理对象 -->
<bean id="linaProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="lina"/>
<property name="interceptorNames" value="sleepHelperAdvisor"/>
</bean>

如配置文件中:

pattern属性指定了正则表达式,他匹配所有的sleep方法

使用org.springframework.aop.support.DefaultPointcutAdvisor的目的是为了使切点和增强结合起来形成一个完整的切面

最后配置完后通过org.springframework.aop.framework.ProxyFactoryBean产生一个最终的代理对象。

2、纯简单java对象切面

纯简单java对象切面这话怎么说呢,在我看来就是相对于第一种配置,不需要使用代理,,而是通过spring的内部机制去自动扫描,这时候我们的配置文件就该如下修改:

<!-- 创建一个增强 advice -->
<bean id ="sleepHelper" class="com.tgb.springaop.aspect.SleepHelper"/>
<!-- 目标类 -->
<bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/> <!-- 配置切点和通知-->
<bean id ="sleepAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="sleepHelper"></property>
<property name="pattern" value=".*sleep"/>
</bean> <!-- 自动代理配置 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

是不是相对于第一种简单了许多,不用再去配置代理了。

3、@Aspect注解形式

根据我们的经验也知道,注解的形式相对于配置文件是简单一些的,这时候需要在已有的方法或类上家注解:

/**
* 通过注解的方式 添加增强
* @author 陈丽娜
* @version 2015年5月31日上午10:26:13
*/ @Aspect
@Component
public class SleepHelper03 {
/*@Pointcut("execution(* com.tgb.springaop.service.impl..*(..))")*/
@Pointcut("execution(* *.sleep(..))")
public void sleeppoint(){} @Before("sleeppoint()")
public void beforeSleep(){
System.out.println("睡觉前要敷面膜");
} @AfterReturning("sleeppoint()")
public void afterSleep(){
System.out.println("睡觉后要做美梦");
}

配置文件中只需写:

<!--扫描包 -->
<context:component-scan base-package="com.tgb" annotation-config="true"/>
<!-- ASPECTJ注解 -->
<aop:aspectj-autoproxy proxy-target-class="true" /> <!-- 目标类 -->
<bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/>

4、注入形式的Aspcet切面

个人感觉这个是最简单的也是最常用的,也是最灵活的。配置文件如下:

<!-- 目标类 -->
<bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/>
<bean id ="sleepHelper" class="com.tgb.springaop.aspect.SleepHelper02"/> <aop:config>
<aop:aspect ref="sleepHelper">
<aop:before method="beforeSleep" pointcut="execution(* *.sleep(..))"/>
<aop:after method="afterSleep" pointcut="execution(* *.sleep(..))"/>
</aop:aspect>
</aop:config>

配置文件中提到的SleepHelper02类如下:

/**
* 通过注解的方式 添加增强
* @author 陈丽娜
* @version 2015年5月31日上午10:26:13
*/ public class SleepHelper02 { public void beforeSleep(){
System.out.println("睡觉前要敷面膜");
} public void afterSleep(){
System.out.println("睡觉后要做美梦");
}
}

参考:http://itindex.net/detail/53556-spring-aop

spring aop的更多相关文章

  1. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  2. 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...

  3. spring aop注解方式与xml方式配置

    注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...

  4. 基于Spring AOP的JDK动态代理和CGLIB代理

    一.AOP的概念  在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的 ...

  5. Spring AOP详解

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  6. Spring AOP实例——异常处理和记录程序执行时间

    实例简介: 这个实例主要用于在一个系统的所有方法执行过程中出线异常时,把异常信息都记录下来,另外记录每个方法的执行时间. 用两个业务逻辑来说明上述功能,这两个业务逻辑首先使用Spring AOP的自动 ...

  7. 从零开始学 Java - Spring AOP 实现用户权限验证

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就 ...

  8. 从零开始学 Java - Spring AOP 实现主从读写分离

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  9. 从零开始学 Java - Spring AOP 拦截器的基本实现

    一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...

随机推荐

  1. 使用JSONObject.fromObject的时候出现“There is a cycle in the hierarchy”异常 的解决办法

    在使用JSONObject.fromObject的时候,出现“There is a cycle in the hierarchy”异常.   意思是出现了死循环,也就是Model之间有循环包含关系: ...

  2. 移动端访问PC站点时自动跳转至移动站点

    方法一: 百度Site APP的uaredirect.js 实现手机访问,自动跳转 <script src="http://siteapp.baidu.com/static/webap ...

  3. JAVA程序员常用软件整理下载

    ********为了大家学习方便,特意整理软件下载如下:*************Java类软件:-------------------------------JDK7.0:http://pan.ba ...

  4. iOS架构一个中型普通App的一些经验总结

    这一版比较完善的的App终于提交审核了.有时间写写自己的一些经验的总结了.自己主导的从0到比较成型的app到目前来说也只有两个,但是其中的很多东西都是大同小异.基本上是想到了什么就写什么,感觉写的不到 ...

  5. Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  6. [数据结构]——链表(list)、队列(queue)和栈(stack)

    在前面几篇博文中曾经提到链表(list).队列(queue)和(stack),为了更加系统化,这里统一介绍着三种数据结构及相应实现. 1)链表 首先回想一下基本的数据类型,当需要存储多个相同类型的数据 ...

  7. 【从零开始学BPM,Day1】工作流管理平台架构学习

    [课程主题] 主题:5天,一起从零开始学习BPM [课程形式] 1.为期5天的短任务学习 2.每天观看一个视频,视频学习时间自由安排. [第一天课程] Step 1 软件下载:H3 BPM10.0全开 ...

  8. Android 微信第三方登录(个人笔记)

    今天在写微信登录,花了半天时间搞定.然后写下自己的笔记,希望帮助更多的人...欢迎各位指教. 微信授权登录,官方说的不是很清楚.所以导致有一部分的坑. 微信注册应用平台的应用签名,下载 微信签名生成工 ...

  9. 用ffmpeg快速剪切和合并视频

    如果直接找视频剪切和合并视频的软件,通常出来的都是大的视频编辑软件或者是有图形界面的剪切软件,大型一点的功能太多安装麻烦,小型一点的功能可能不齐全. 只是简单的剪切或者一下合并一下,还是ffmpeg这 ...

  10. 详解this

    this 虐我千百遍,看完此文效立见!不得不说,这篇文章的总结很地道很全面,适合收藏之用. 原文:all this 习惯了高级语言的你或许觉得JavaScript中的this跟Java这些面向对象语言 ...