spring ioc以及aop原理,springmvc aop原理,深入浅析Spring 的aop实现原理

spring ioc以及aop原理,springmvc aop原理,深入浅析Spring 的aop实现原理

AOP(面向方面编程)可以说是OOP(面向对象编程)的补充和完善。本文介绍了Spring的aop实现原理,让感兴趣的朋友一起学习。

什么是AOP

AOP(面向方面编程)可以说是OOP(面向对象编程)的补充和完善。OOP引入了封装、继承和多态的概念来建立一个对象层次结构来模拟一组公共行为。当我们需要为分散的对象引入公共行为时,OOP是无能为力的。也就是说,OOP允许你从上到下定义关系,但不适合从左到右定义关系。比如日志功能。日志通常水平分布在所有对象层次结构中,与它们所分布到的对象的核心功能无关。其他类型的代码也是如此,比如安全性、异常处理和透明持久性。这种分散在各处的无关代码叫做横切代码。在OOP设计中,导致大量的代码重复,不利于各个模块的重用。

简介

代理模式,前段时间写的一个java设计模式,最近在看Spring Aop的时候感觉应该和代理模式有密切关系,所以决定了解一下Spring Aop的实现原理。

说到AOP,就不得不说OOP,它引入封装、继承、多态等概念建立一个对象层次来模拟一组公共行为。但是,如果我们需要为某些对象引入公共部分,OOP会引入大量重复代码。比如:日志功能。

AOP技术使用一种叫做“横切”的技术来解剖封装对象的内部,将那些影响多个类的公共行为封装成一个可复用的模块,这样可以减少系统的重复代码,降低模块之间的耦合度,有利于以后的可操作性和可维护性。AOP将软件系统分为两部分:核心关注点和横切关注点。主要业务流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,它们经常出现在核心关注点的很多地方,而且所有的地方基本上都是相似的。例如授权认证、日志记录和事务处理。

实现原理 

在前面学习agent模式的时候,我了解到agent模式可以分为动态agent和静态agent。现在,我们将首先基于代理模式实现我们自己的AOP框架,然后研究Spring的AOP的实现原理。

首先,实现静态代理。静态代理的关键是实现代理对象和目标对象的公共接口,代理对象持有目标对象的引用。

公共接口代码:

公共接口IHello {

/**

*商业方法

* @param str

*/

void sayHello(字符串str);

}

类别代码:

公共类Hello实现IHello{

@覆盖

public void sayHello(String str) {

system . out . println(' hello ' str);

}

}

类代码,我们给它添加日志功能,在方法启动前后执行特定的方法。是不是和AOP特别像?

公共类ProxyHello实现IHello{

二等兵IHello你好;

公共代理Hello(IHello hello) {

super();

this.hello=hello

}

@覆盖

public void sayHello(String str) {

logger . start();//添加特定的方法

hello . say hello(str);

logger . end();

}

}

日志类代码:

公共类记录器{

公共静态void start(){

System.out.println(new Date()'说你好开始.');

}

公共静态void end(){

system . out . println(new Date()' say hello end ');

}

}

测试代码:

公共类测试{

公共静态void main(String[] args) {

IHello Hello=new proxy Hello(new Hello());//如果我们需要日志功能,请使用代理类

//IHello Hello=new Hello();//如果我们不需要log函数,就使用目标类

Hello.sayHello('明天');

}

}

这样我们实现了最简单的AOP,但是会有一个问题:如果我们有很多像Hello这样的类,是不是也要写很多像HelloProxy这样的类?其实也是一件很麻烦的事情。jdk1.3之后,jdk为我们提供了一个API Java . lang . reflect . invocation handler的类,允许我们在JVM调用一些方法的时候,动态地为它们做一些事情。让我们实现动态代理。

动态代理实现主要是实现InvocationHandler的方法,将目标对象注入代理对象,利用反射机制执行目标对象。

接口的实现与静态代理相同,代理类代码为:

公共类DynaProxyHello实现InvocationHandler{

私有对象目标;//目标对象

/**

*通过反射实例化目标对象

* @param对象

* @返回

*/

公共对象绑定(对象对象){

this.target=object

返回proxy . newproxyinstance(this . target . getclass()。getClassLoader()、this.target.getClass()。getInterfaces(),this);

}

@覆盖

公共对象调用(对象代理、方法方法、对象[]参数)

可投掷的

对象结果=null

logger . start();//添加其他方法

//通过反射机制运行目标对象的方法

result=method . invoke(this . target,args);

logger . end();

返回结果;

}

}

  测试类代码:

公共类DynaTest {

公共静态void main(String[] args) {

IHello hello=(IHello)新DynaProxyHello()。bind(new Hello());//如果我们需要日志功能,请使用代理类

//IHello Hello=new Hello();//如果我们不需要log函数,就使用目标类

Hello.sayHello('明天');

}

}

看了上面的代码,对比Spring AOP可能会有问题。log类只能在方法之前和之后打印,但是AOP在条件满足的情况下应该是可以执行的。那么,有没有可能将DynaPoxyHello对象与日志操作对象(Logger)解耦呢?

请看下面的代码实现,它将把DynaPoxyHello对象从日志操作对象(Logger)中分离出来:

如果我们想在代理对象的方法之前或之后添加日志操作码(或其他操作码),那么我们可以抽象一个接口。这个接口只有两个方法:一个是代理对象执行方法之前执行的方法,我们称之为start,第二个是代理对象执行方法之后执行的方法,我们称之为end。

Logger的接口:

公共接口ILogger {

void start(方法Method);

void end(方法方法);

}

记录器的接口实现:

公共类DLogger实现ILogger{

@覆盖

公共void开始(方法方法){

system . out . println(new Date()method . getname()' say hello start . ');

}

@覆盖

公共void end(方法method) {

system . out . println(new Date()method . getname()' say hello end ');

}

}

 动态代理类:

公共类DynaProxyHello实现InvocationHandler{

//调用对象

私有对象代理;

//目标对象

私有对象目标;

公共对象绑定(对象目标、对象代理){

this.target=target

this.proxy=proxy

返回proxy . newproxyinstance(this . target . getclass()。getClassLoader()、this.target.getClass()。getInterfaces(),this);

}

@覆盖

公共对象调用(对象代理、方法方法、对象[]参数)

可投掷的

对象结果=null

//Reflect以获取运算符的示例

class clazz=this . proxy . getclass();

//反射以获取运算符的开始方法

method start=clazz . getdeclaredmethod(' start ',new Class[]{ method . Class });

//反射执行start方法

start.invoke(this.proxy,new Object[]{ this . proxy . getclass()});

//执行要处理的对象的原始方法

方法.调用(this.target,args);

//反射以获取运算符的结束方法

method end=clazz . getdeclaredmethod(' end ',new Class[]{ method . Class });

//反射执行end方法

end.invoke(this.proxy,新对象[]{ method });

返回结果;

}

}

测试代码:

公共类DynaTest {

公共静态void main(String[] args) {

IHello hello=(IHello)新DynaProxyHello()。bind(new Hello()、new DLogger());//如果我们需要日志功能,请使用代理类

//IHello Hello=new Hello();//如果我们不需要log函数,就使用目标类

Hello.sayHello('明天');

}

}

通过上面的例子可以发现,通过动态代理和启动技术,AOP的功能已经基本实现。如果只需要在方法执行前打印日志,可以不实现end()方法,这样就可以控制打印的时间。如果要让指定的方法打印日志,我们只需要在invoke()方法中添加一个对方法名称的判断,方法名称就可以写入xml文件中,这样就可以实现与配置文件的解耦,从而实现了一个简单的spring aop框架。

以上是边肖介绍的Spring的aop实现原理。希望对你有帮助!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: