2015第29周二AOP

1、问题:想要添加日志记录、性能监控、安全监测

2、最初解决方案

2.1、最初解决方案:在每个需要的类函数中重复写上面处理代。

缺点:太多重复代码,且紧耦合

2.2、抽象类进行共性设计,子类进行个性设计,此处不讲解,缺点一荣俱荣,一损俱损

2.3、使用装饰器模式/代理模式改进的解决方案

装饰器模式:动态地给一个对象添加一些额外的职责。就增加功能来说, 装饰器模式相比生成子类更为灵活。

代理模式:为其他对象提供一种代理以控制对这个对象的访问。

缺点:紧耦合,每个业务逻辑需要一个装饰器实现或代理

2.4、JDK动态代理解决方案(比较通用的解决方案)

Java代码  

1. 
public class MyInvocationHandler implements InvocationHandler {

2. 
private Object
target;

3. 
public MyInvocationHandler(Object
target) {

4. 
this.target = target;

5. 
}

6. 
@Override

7. 
public Object
invoke(Object proxy, Method method, Object[] args) throws Throwable {

8. 
//1.记录日志 2.时间统计开始 3.安全检查

9. 
Object retVal = method.invoke(target, args);

10.
//4.时间统计结束

11.
return retVal;

12.
}

13.
public static Object proxy(Object target) {

14.
return Proxy.newProxyInstance(target.getClass().getClassLoader(),

15.
target.getClass().getInterfaces(), new MyInvocationHandler(target));

16.
}

17.
}

编程模型

Java代码  

1. 
//proxy 在其上调用方法的代理实例

2. 
//method 拦截的方法

3. 
//args 拦截的参数

4. 
Override

5. 
public Object
invoke(Object proxy, Method method, Object[] args) throws Throwable {

6. 
Object retVal=null;

7. 
//预处理

8. 
//前置条件判断

9. 
boolean ok
true;

10.
if(!ok) {//不满足条件

11.
throw new RuntimeException("你没有权限");

12.
}

13.
else {//反射调用目标对象的某个方法

14.
retVal = method.invoke(target, args);

15.
}

16.
//后处理

17.
return retVal;

18.
}

19.

缺点:使用麻烦,不能代理类,只能代理接口

CGLIB动态代理解决方案(比较通用的解决方案)

Java代码  

1. 
public class MyInterceptor implements MethodInterceptor {

2. 
private Object
target;

3. 
public MyInterceptor(Object
target) {

4. 
this.target = target;

5. 
}

6. 
@Override

7. 
public Object
intercept(Object proxy, Method method, Object[] args,

8. 
MethodProxy invocation) throws Throwable {

9. 
//1.记录日志 2.时间统计开始 3.安全检查

10.
Object retVal = invocation.invoke(target, args);

11.
//4.时间统计结束

12.
return retVal;

13.
}

14.
public static Object proxy(Object target) {

15.
return Enhancer.create(target.getClass(), new MyInterceptor(target));

16.
}

17.
}

编程模型

Java代码  

1. 
//proxy 在其上调用方法的代理实例 method拦截的方法 args 拦截的参数

2. 
//invocation
用来去调用被代理对象方法的

3. 
@Override

4. 
public Object
intercept(Object proxy, Method method, Object[] args,

5. 
MethodProxy invocation) throws Throwable {

6. 
//预处理

7. 
//前置条件判断

8. 
boolean ok
true;

9. 
if(!ok) {//不满足条件

10.
throw new RuntimeException("出错了");

11.
}

12.
else {//调用目标对象的某个方法

13.
Object retVal = invocation.invoke(target, args);

14.
}

15.
//后处理

16.
return retVal;

17.
}

优点:能代理接口和类

缺点:使用麻烦,不能代理final类

动态代理本质

本质:对目标对象增强

最终表现为类(动态创建子类),看手工生成(子类)还是自动生成(子类)

代理限制:

只能在父类方法被调用之前或之后进行增强(功能的修改),不能在中间进行修改,要想在方法调用中增强,需要ASM(java 字节码生成库)

其他动态代理框架

jboss:javassist (hibernate 3.3中默认为javassist)

(hibernate 3.3之前中默认为cglib)

2.5、AOP解决方案(通用且简单的解决方案)

Java代码  

1. 
@Aspect

2. 
public class PayEbiAspect {

3. 
@Pointcut(value="execution(*
pay(..))")

4. 
public void pointcut() {}

5. 
@Around(value="pointcut()")

6. 
public Object
around(ProceedingJoinPoint pjp) throws Throwable {

7. 
//1.记录日志

8. 
//2.时间统计开始

9. 
//3.安全检查

10.
Object retVal = pjp.proceed();//调用目标对象的真正方法

11.
//4.时间统计结束

12.
return retVal;

13.
}

14.
}

编程模型

Java代码  

1. 
//2 切入点

2. 
@Pointcut(value="execution(*
*(..))")

3. 
public void pointcut() {}

4. 
//3 拦截器的interceptor

5. 
@Around(value="pointcut()")

6. 
public Object
around(ProceedingJoinPoint pjp) throws Throwable {

7. 
Object retVal=null;

8. 
//预处理

9. 
//前置条件判断

10.
boolean ok
true;

11.
if(!ok) {//不满足条件

12.
throw new RuntimeException("你没有权限");

13.
}

14.
else {//调用目标对象的某个方法

15.
retVal = pjp.proceed();

16.
}

17.
//后处理

18.
return retVal;

19.
}

缺点:依赖AOP框架

AOP入门

概念:

n关注点:可以认为是所关注的任何东西,比如上边的支付组件;

n关注点分离:将问题细化为单独部分,即可以理解为不可再分割的组件,如上边的日志组件和支付组件;

n横切关注点:会在多个模块中出现,使用现有的编程方法,横切关注点会横越多个模块,结果是使系统难以设计、理解、实现和演进,如日志组件横切于支付组件。

织入:横切关注点分离后,需要通过某种技术将横切关注点融合到系统中从而完成需要的功能,因此需要织入,织入可能在编译期、加载期、运行期等进行。

nAOP是什么(Aspect Oriented Programming)

AOP是一种编程范式,提供从另一个角度来考虑程序结构以完善面向对象编程(OOP)。

AOP为开发者提供了一种描述横切关注点的机制,并能够自动将横切关注点织入到面向对象的软件系统中,从而实现了横切关注点的模块化。

AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

nAOP能干什么,也是AOP带来的好处

1降低模块的耦合度

2使系统容易扩展

3设计决定的迟绑定:使用AOP,设计师可以推迟为将来的需求作决定,因为它

可以把这种需求作为独立的方面很容易的实现。

4更好的代码复用性

AOP基本概念

连接点(Joinpoint):

表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点,AOP中表示为在哪里做

切入点(Pointcut):

选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法,AOP中表示为在哪里做的集合

增强(Advice):或称为增强

在连接点上执行的行为,增强提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置增强(before advice)、后置增强 (after advice)、环绕增强 (around advice),在Spring中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入增强 ;AOP中表示为做什么

方面/切面(Aspect):

横切关注点的模块化,比如上边提到的日志组件。可以认为是增强、引入和切入点的组合;在Spring中可以使用Schema和@AspectJ方式进行组织实现;AOP中表示为在哪里做和做什么集合

目标对象(Target Object):

需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被增强的对象,从而也可称为“被增强对象”;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象,AOP中表示为对谁做

AOP代理(AOP Proxy):

AOP框架使用代理模式创建的对象,从而实现在连接点处插入增强(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。

织入(Weaving):

织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期进行。

引入(inter-type
declaration
):

也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象), AOP中表示为做什么(新增什么)

AOP的Advice类型

前置增强(Before advice):

在某连接点之前执行的增强,但这个增强不能阻止连接点前的执行(除非它抛出一个异常)。

后置返回增强(After returning
advice
):

在某连接点正常完成后执行的增强:例如,一个方法没有抛出任何异常,正常返回。

后置异常增强(After throwing
advice
):

在方法抛出异常退出时执行的增强。

后置最终增强(After (finally)
advice
):

当某连接点退出的时候执行的增强(不论是正常返回还是异常退出)。

环绕增强(Around Advice):

包围一个连接点的增强,如方法调用。这是最强大的一种增强类型。 环绕增强可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。

横切关注点的表现有:  

  ·代码纠结/混乱——当一个模块或代码段同时管理多个关注点时发生这种情况。如我既要实现业务、还要实现安全和事务。即有些关注点同时被多个不同的模块实现。实现了重复的功能。

  ·代码分散——当一个关注点分布在许多模块中并且未能很好地局部化和模块化时发生这种情况 。如许多模块调用用户是否登录验证代码。调用了重复的功能。

AOP包括三个清晰的开发步骤:

1:功能横切:找出横切关注点。

2:实现分离:各自独立的实现这些横切关注点所需要完成的功能。

3:功能回贴:在这一步里,方面集成器通过创建一个模块单元—— 方面来指定重组的规则。重组过程——也叫织入或结合—— 则使用这些信息来构建最终系统。

来源:http://jinnianshilongnian.iteye.com/blog/1474325

来自为知笔记(Wiz)

时间: 2024-10-23 11:42:54

2015第29周二AOP的相关文章

2015第29周五AOP

AOP使用场景 AOP用来封装横切关注点,具体可以在下面的场景中使用: Authentication 权限 Caching 缓存 Context passing 内容传递 Error handling 错误处理 Lazy loading 懒加载 Debugging 调试 logging, tracing, profiling and monitoring 记录跟踪 优化 校准 Performance optimization 性能优化 Persistence 持久化 Resource pooli

2015.7.29学习内容

2015.7.29学习内容 一.Switch选择结构 1.回顾 01.在Java中如何产生一个随机数 Math.random()    随机数范围:0到1,能取到0,取不到1 02.equals(): 在Java中,如果比较两个字符串用==的话,会出现错误,所以以后我们只要是对字符串类型进行对比,统一使用equals方法 2.Switch选择结构 Switch(char/int){ case 1: //语句 break; case 2: //语句2 break; default: //默认语句

2015.12.29~2015.12.30真题回顾!-- HTML5学堂

2015.12.29~2015.12.30真题回顾!-- HTML5学堂 吃饭,能够解决饥饿,提供身体运作机能.练习就像吃饭,强壮自己,提升编程技能,寻求编程技巧的最佳捷径!吃饭不能停,练习同样不能停哦! HTML5真题[2015.12.29]题目 学习JavaScript或应用JavaScript进行脚本开发,“变量”这是必须要学会使用的.什么是变量呢?又什么作用呢?ok,大家稍安勿躁哦,试体验体验这题目<HTML5真题[2015.12.29]题目>与 <HTML5真题[2015.12

2014第29周二

比较郁闷的一天,早上各种差错迟到了2分钟,然后上午还没解决好cookie登录的问题,就说要帮忙演示,然后是上周做的定制后面发现的问题,下午及晚上花了很长时间修改测试验证,再次给自己留下深刻的教训,在自己测试时一定不能偷懒和假定,按照用户的操作把所有的过程都走一遍并注意观察结果考虑里面的问题,而不能想当然的怕一些重要的问题麻烦而不去测试,后面只会给自己带来更大的麻烦,也让别人对你个人的能力和信任度降低. 在代码开发上今天遇到几个问题:1.设置cookie问题,创建cookie要设置有效期,值设置为

2015/9/29 Python基础(20):类的授权

类的授权 1.包装包装在Python编程世界中时经常会被提到的一个术语.它是一个通用的名字,意思是对一个已存在的对象进行包装,不管它是数据类型,还是一段代码,可以是对一个已存在的对象,增加新的,删除不要的,或者修改其他已存在的功能.在Python2.2以前,从Python的标准类型子类化或派生类都是不允许的,即使你现在可以这么做,这种做法也并不多.你可以包装任何类型作为一个类的核心成员,以使新对象的行为模仿你想要的数据类型中已存在的行为,并且去掉你不希望存在的行为:它可能会要做一些额外的事情.这

2015第14周二

今天调试程序时发现自己犯了一个很弱智的错误,先把实体类保存到数据库中再修改它的某个属性,结果当然修改后的属性值没保存到数据库中,赶紧调整顺序后解决,之前写那端程序时太不小心了,惭愧.今天用sql语句更新一个列的值加1时发现总不成功,后来看该列值为null,用它做加法当然不行,然而sql语句也没报错误,后来把列默认值设为0后解决. 今天三月最后一天,2015第一个季度完了,第二个季度要更加努力进步.工作.生活.

2015第7周二技术学习

IE下使用jQuery重置iframe地址时内存泄露问题解决办法 页面中有个iframe: ? 1 2  <iframe src='a.html'></iframe> <button>测试IFRAME泄露</button> 其中a.html内容如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 3

2015第29周日

记下这周的流水账,今天看了2小时多电影碟中谍,2多小时视频欢乐喜剧人,1个多小时搜书找书,把杭图有的关于Spring相关的书都找到借了,突然感觉自己这样效率太低,很多都可以直接在网上下载到清晰的电子版,并且这些书收集借来不重要,重要的是吸收里面的精华内容,像这里面很多书很多都是几年前翻过的,希望这次再看能有更透彻的领悟.另外花了大部分时间听了明朝那些事的朱元璋后半部分,站在事后600多年回顾之前历史,评价那时掌握天下的人每个抉择的对错,看他们的眼光格局用人做事的局限和水平,其中不少触动内心的地方

2015第24周二Spring事务2

今天继续深入学习SPring事务,发现网上很多文章都是很相似的转载没多少价值,就觉得更有必要把这个主题深入下去,先是摘录那些对自己有用的观点,后期再结合源码进行全面的整理. Spring提供了许多内置事务管理器实现,常用的有以下几种: DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,数据源事务管理器,提供对单个javax.sql.DataSource事务管理,用于Spring JDBC抽象框架.iBATIS