1.什么是IOC?
IOC即Inverse of Control,它包括两个内容:控制与反转
那到底什么东西的“控制”被“反转”了呢?对于软件而言,即是某一个接口具体实现类的选择控制权从调用类中移除,转交给第三方决定。
因为IOC确实不够开门见山,因此业界曾经进行了广泛的讨论,最终软件界的泰斗级人物Martin Fowler提出了DI(依赖注入:Dependency Injection)的概念用以代替IOC
即让调用类对某一个接口的依赖关系由第三方(容器或者协作类)注入,以移除调用类对某一个接口实现类的依赖。
2.什么是AOP?
AOP是Aspect Oritened Programming的简称,普遍翻译成 面向切面编程。
按照软件重构思想的理念,如果多个类中出现相同的代码,应该考虑定义一个共同的抽象类,将这些相同的代码提取到抽象类中。
比如,Horse、Pig、Camel这些对象都有run、eat方法,通过引入一个包含这两个方法抽象的Animal父类,Horse、Pig、Camel就可以通过继承Animal复用run和eat方法。
通过引入父类消除多个类中重复代码的方式在大多情况下是可行的,但世界并非永远这么简单。
举个事务管理的栗子,看下面代码
在上面的代码中,真正的业务逻辑就只有
其他的逻辑都可以称之为横切逻辑,这些横切逻辑依附在业务方法的流程中,我们无法将之转移到其他地方去。
AOP独辟蹊径通过横向抽取机制为这类无法通过纵向继承体系进行抽象的重复性代码提供了解决方案。
Spring AOP使用动态代理技术在运行期织入增强的代码。
3.Spring AOP使用了两种代理机制:一种是基于JDK的动态代理;另一种是基于CGLib的动态代理,请简述?
之所以需要两种代理机制,很大程度上市因为JDK本身只提供接口的代理,而不支持类的代理。
JDK动态代理:
JDK动态代理主要涉及到java.lang.reflect包中两个类:Proxy和InvocationHandler。
其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑和业务逻辑编织在一起。所以我们可以将InvacationHandler看成是一个编织器
而Proxy利用InvacationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
具体的流程为:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentExceptionloader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
使用JDK动态代理有一个限制,即它只能为接口创建代理实例,这一点我们可以从newProxyInstance方法的签名中就看的很清楚:
第二个入参interfaces就是需要代理实例实现的接口列表。
虽然面向接口编程的思想被很多大师级人物推崇,但在实际开发中,许多开发者也对此深感疑惑:难道对一个简单的业务表的操作也要老老实实的创建5个类(领域对象类、Dao接口、Dao实现类、Service接口和Service实现类)吗?难道不能直接通过实现类构造程序吗?对于这个问题,我们很难给出一个熟好熟劣的准确判断,但我们确实发现有很多不适用接口的项目也取得了很好的效果。
对于没有通过接口定义业务方法的类,如何动态创建代理实例呢?JDK的代理技术显然已经黔驴技穷,CGLib作为一个替代者,填补了这个空缺。