IOC过程:
-
加载 xml 配置文件,遍历其中的标签
-
遍历标签,通过反射加载 beanClass,Class.forName(className),创建bean,beanClass.newInstance()
-
遍历 标签,利用反射将 bean 相关字段访问权限设为可访问,将属性和引用的字段填充进bean
-
将 bean 注册到 bean 容器中 beanMap.put(id, bean);
IOC 容器解决循环依赖
缓存 | 用途 |
---|---|
singletonObjects | 用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用 |
earlySingletonObjects | 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖。”早期引用“是指向原始对象的引用。 |
singletonFactories | 存放 bean 工厂对象,用于解决循环依赖 |
``Spring IOC解决循环依赖是依靠缓存。IOC的加载过程是 创建bean实例,属性实例注入,回调实例实现的接口方法。在创建bean实例,尚未注入属性实例之前,Spring将未填充属性的bean加入到二级缓存中,当bean引用到依赖的实例时先从缓存中获取空壳的bean,也就是“早期引用”。当被引用的bean被实例化后再去一级缓存中读取到可以直接使用的bean。A对象的创建需要引用到B对象,而B对象的创建也需要A对象,而此时当B对象创建的时候直接从缓存里引用A对象(虽然不是完全体A对象,毕竟没有赋值处理),当B对象完成创建以后再被A对象引用进去,则A对象也完成了创建。`
-
AOP过程:
-
获取所有的切面类。
-
遍历容器中的类。
-
使用 AspectJ 表达式筛选通知器
AOP 中,切点 Pointcut 是用来匹配连接点的,以 AspectJExpressionPointcut 类型的切点为例。该类型切点实现了ClassFilter 和 MethodMatcher 接口,匹配的工作则是由 AspectJ 表达式解析器复杂。除了使用 AspectJ 表达式进行匹配,Spring 还提供了基于正则表达式的切点类,以及更简单的根据方法名进行匹配的切点类。
-
尝试进行Aspect的织入 : 首先按照order的值进行升序排序,确保order值小的aspect先织入
-
Spring 是如何将 AOP 和 IOC 模块整合到一起的
即通过拓展点 BeanPostProcessor 接口
-
最后调用Enhancer.create(targetClass, methodInterceptor),返回的的 bean 是代理对象,而非原始的 bean
-
AopContext.currentProxy()
用于获取当前的代理对象。当 expose-proxy 被配置为 true 时,该代理对象会被放入 ThreadLocal 中,通过getBean方式得到的对象就已经是代理对象了,可以直接通过对象.目标方法
AopUtils.isAopProxy(bean) : 是否是代理对象;
AopUtils.isCglibProxy(bean) : 是否是CGLIB方式的代理对象;
AopUtils.isJdkDynamicProxy(bean) : 是否是JDK动态代理方式的代理对象;
要想启用Spring AOP,配置类加上注解@EnableAspectJAutoProxy,会往spring容器注入一个BeanPostProcessor即AnnotationAwareAspectJAutoProxyCreator
在Bean实例化完成后(即调用构造函数将对象创建出来)会执行AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization(这个方法在父类AbstractAutoProxyCreator中,AnnotationAwareAspectJAutoProxyCreator并没有重写)
当执行完成AbstractAutoProxyCreator#postProcessAfterInitialization这个方法会将原生对象变成代理代理对象,代理对象中写入了横切的逻辑
什么是 AOP
AOP(Aspect-Oriented Programming), 即 面向切面编程 , 它与 OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与 OOP 不同的抽象软件结构的视角. 在 OOP 中, 我们以类(class)作为我们的基本单元, 而 AOP 中的基本单元是 Aspect(切面)。AOP要达到的效果是保证开发者在不修改代码的前提下,为系统中某些不同的组件提供一些公共的功能。
SpringAOP优点?
- 集中处理某一关注点/横切逻辑
- 可以很方便的添加/删除关注点
- 侵入性少,增强代码可读性及维护性
SpringAOP实际应用举例?
比如我们用Dubbo对外提供服务,里面有个多个方法,为了不给调用方奇怪的错误,会把每个方法里的异常都catch主,只返回一个result,调用方会根据这个result的success判断此次是否调用成功。如果服务里所有的方法都有这样相同的处理逻辑,那么此时就用上了AOP
比如特殊权限验证,参数修正等操作。
I,记录日志。
II,监控性能。
III,权限控制。
IV,缓存优化。
V,事务管理。
Spring AOP不支持代理类内部方法调用的拦截
在spring的源代码中通过一个增强对象的检查,控制了当前的内部调用是否使用代理来执行
因为目标方法是通过代理类调用的,但是内部调用属于普通调用,所以无法触发拦截,所以需要通过上下文获取代理类
public class BeanA{
public void method1(){
method2();
}
public void method2(){
...
}
}
public void method1(