文章目录
参考:https://blog.csdn.net/weixin_36380516/article/details/113904400
一、aop使用
注解类 TimeLog
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeLog {
String invokename() default "";
String prefix() default "";
}
LogAspect 切面类
@Component
@Aspect
public class LogAspect {
@Before("@annotation(TimeLog)")
public void logBefore() {
System.out.println("logBefore ~~~~~");
}
@After("@annotation(TimeLog)")
public void logAfter() {
System.out.println("logAfter ~~~~~");
}
}
AopController 目标类
@Controller
public class AopController {
@TimeLog(invokename = "AopController.requestTest", prefix = "requestTest")
public void requestTest() {
System.out.println("requestTest 启动~~");
}
}
AopControllerTest 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class AopControllerTest {
@Test
public void test() {
ApplicationContext applicationContext = ApplicationContextHolder.getContext();
AopController aopController = (AopController) applicationContext.getBean("aopController");
}
}
二、三级缓存验证
1、有AOP
,无循环依赖
项目初始化时,创建单例bean
AbstractBeanFactory#doGetBean
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
//--------
// Create bean instance.
if (mbd.isSingleton()) {
// 获取单例bean
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//创建Bean
return createBean(beanName, mbd, args);
}
-----
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
return (T) bean;
}
获取单例bean,并缓存到一级缓存singletonObjects,删除三级缓存中的bean
DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
//回调 createBean 方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
if (newSingleton) {
// 添加单例Bean到一级缓存 singletonObjects
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
单例bean实例化、依赖注入和初始化(内部aop增强),并缓存到三级缓存 singletonFactories
中
AbstractAutowireCapableBeanFactory#doCreateBean
//真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) {
// Instantiate the bean.
//封装被创建的Bean对象
BeanWrapper instanceWrapper = null;
//---1--- 实例化Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
//向容器中缓存单例模式的Bean对象,以防循环引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// **************** 缓存到 singletonFactories三级缓存中
//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用. 缓存到 singletonFactories三级缓存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//Bean对象的初始化,依赖注入在此触发
//这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
Object exposedObject = bean;
try {
//---2--- 依赖注入
//将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
populateBean(beanName, mbd, instanceWrapper);
//---3--- 初始化bean
//初始化Bean对象,并aop增强
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
return exposedObject;
}
这里三级缓存没有任何用处,初始完成后三级缓存中观察的bean缓存情况如下:
一级缓存 singletonObjects: 缓存 aopController
二级缓存 earlySingletonObjects: 未缓存 aopController
三级缓存 singletonFactories: 缓存 aopController,缓存到一级缓存后删除
2、无aop,有循环依赖
这里
3、有aop,有循环依赖
AService、BService aop增强并循环依赖。
这里先创建AService对象,依赖注入时需要getBean(“bService”),接着创建BService对象,依赖注入时需要获取 AService对象,通过三级缓存获取AService对象,代码如下:
AbstractBeanFactory#doGetBean
//真正实现向IOC容器获取Bean的功能,也是触发依赖注入功能的地方
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
//如果指定的是别名,将别名转换为规范的Bean名称
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//先从缓存中取是否已经有被创建过的单态类型的Bean
//对于单例模式的Bean整个IOC容器中只创建一次,不需要重复创建; 比如循环依赖注入时,从缓存中获取bean
Object sharedInstance = getSingleton(beanName);
//IOC容器创建单例模式Bean实例对象
if (sharedInstance != null && args == null) {
……
}
……
}
调用 getSingleton 代码获取AService
对象实例
DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从二级缓存中获取对象,
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 为何对象从三级缓存中删除,放入二级缓存中呢? aop 一般是类初始化后增加的,aop循环依赖则是在下面代理增强的。
// 解决多个aop类循环依赖,放入二级缓存, 后面初始化此类时,查询到已经有代理过的对象,就不会创建代理对象了,保证代理类的唯一
singletonObject = singletonFactory.getObject(); // singletonObject 为代理的实例 beanproxy
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
singletonFactory.getObject()
这里调用匿名内部类方法 getEarlyBeanReference
注意源码 创建Bean时,代码:
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
这里是匿名内部类调用的方法getEarlyBeanREference()
如下,如果被代理增强,返回bean的代理对象
AbstractAutowireCapableBeanFactory#getEarlyBeanReference
//如果bean被代理返回bean的代理对象,如果未被代理,返回bean实例对象
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
一级缓存 singletonObjects:最终缓存了AService代理对象和BService代理对象
二级缓存 earlySingletonObjects: 中间缓存了AService提前生成的代理对象,解决代理循环依赖的问题; 这里如果有个CService,如下图, 二级缓存就有存在的必要了。
三级缓存 singletonFactories:缓存了bean的工厂类
结论
1、没有依赖,有AOP 这种情况中,我们知道 AOP 代理对象的生成是在成品对象创建完成之后创建的,这也是 Spring 的设计原则,代理对象尽量推迟创建。
代理对象为何尽量推迟创建?
2、循环依赖 + AOP 这种情况中, AService 代理对象的生成提前了,因为必须要保证其 AOP 功能,但 BService 代理对象的生成还是遵循的 Spring 的原则。
3、三级缓存各自的作用
第一级缓存存的是对外暴露的对象,也就是我们应用需要用到的
第二级缓存的作用是为了处理循环依赖的对象创建问题,里面存的是半成品对象或半成品对象的代理对象
第三级缓存的作用处理存在 AOP + 循环依赖的对象创建问题,能将代理对象提前创建
三、Spring 为什么要引入第三级缓存
严格来讲,第三级缓存并非缺它不可,因为可以提前创建代理对象
提前创建代理对象只是会节省那么一丢丢内存空间,并不会带来性能上的提升,但是会破环 Spring 的设计原则
Spring 的设计原则是尽可能保证普通对象创建完成之后,再生成其 AOP 代理(尽可能延迟代理对象的生成)
所以 Spring 用了第三级缓存,既维持了设计原则,又处理了循环依赖;牺牲那么一丢丢内存空间是愿意接受的。
四、为何要尽可能延迟代理对象的生成
Spring有自己的设计原则,职责尽量分得细,代理对象的创建尽量放在后面。