c语言sscanf函数的用法是什么
243
2022-09-19
spring-bean生命周期
spring-bean生命周期
文章目录
spring-bean生命周期
一,整体流程二,Bean创建的过程
2.1 bean实例化时机2.2 bean生命周期2.3 bean循环依赖2.4 bean实例化过程2.5 代理对象生成
一,整体流程
二,Bean创建的过程
2.1 bean实例化时机
bean实例化时机分为两类情况:
如果使用BeanFactory来实例化bean,那么所有的bean都是在第一次使用该bean的时候实例化如果使用ApplicationContext来实例化bean
bean的scope是singleton,且lazy-init = false时,则在IOC容器启动初始化时去实例化bean的scope是singleton,且lazy-init = true时,则在第一次使用该bean时才去实例化bean的scope是prototype,则在第一次使用该bean时才去实例化
Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。
2.2 bean生命周期
Bean的实例化主要分为三步:
创建bean实例bean属性注入bean初始化
细化:
bean实例创建bean属性注入检查是否有实现Aware接口
BeanNameAware:实现BeanNameAware清主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的BeanFactoryAware:实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等ApplicationContextAwaer:作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory
检查是否有实现BeanPostProcess接口
如果实现,则在初始化前后都会调用相关方法进行增强
检查是否有自定义初始化方法并且完成bean初始化使用bean检查是否有自定义销毁方法并且完成销毁bean
2.3 bean循环依赖
何为循环依赖?
如何解决?
spring通过三级缓存(三个map)解决了循环依赖这个问题,三级缓存的理论是java基于引用传递,当我们获取到对象的引用时,对象的属性和字段是可以稍后设置的。三级缓存说白了,就是提前暴露bean引用 + 缓存不同阶段的bean
/** 一级缓存:用于存放完全初始化好的 bean **/private final Map
检测循环依赖的过程如下:
A 创建过程中需要 B,于是A 将自己放到三级缓里面,去实例化 BB 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了!
然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 AB 顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)
然后回来接着创建 A,此时 B 已经创建结束,直接从一级缓存里面拿到 B ,然后完成创建,并将自己放到一级缓存里面如此一来便解决了循环依赖的问题
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 1. 尝试去一级缓存中加载我们的bean,IOC容器初始化加载单例bean的时候,第一次进来都会返回null,一级缓存保存的已经处理完成的对象 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) { synchronized(this.singletonObjects) { // 2. 一级缓存找不到从二级缓存中查找 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 3. 二级缓存中找不到去三级缓存中查 ObjectFactory> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); // 获取的还没实例化完成的单例bean会被放入二级缓存 this.earlySingletonObjects.put(beanName, singletonObject); // 移除三级缓存中指定的bean this.singletonFactories.remove(beanName); } } } } return singletonObject; } public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); }
单例bean何时放入一级缓存 ----> 实例化好的bean才会被放入到一级缓存,放入完成后,删除二级和三级缓存中该bean的缓存
protected void addSingleton(String beanName, Object singletonObject) { synchronized(this.singletonObjects) { // 加入到单例缓存池中 this.singletonObjects.put(beanName, singletonObject); // 从三级缓存池中移除(针对的不是处理循环依赖的) this.singletonFactories.remove(beanName); // 从二级缓存中移除(二级缓存中存储的是还没对属性进行赋值的bean) this.earlySingletonObjects.remove(beanName); // 用于保存已经处理的bean this.registeredSingletons.add(beanName); } }
何时放入三级缓存?
如果缓存中没有bean对象,那么Spring会创建Bean对象,将实例化的bean提前曝光,并且加入缓存中。通过三级缓存可以获取到最终引用地址,这也是为什么需要三级缓存的原因。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 这个是实例化Bean的方法,会调用构造方法,生成一个原始类型的Bean instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // 判断是否满足提前暴露bean引用,单例 + 允许循环依赖 + 正在创建 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { // 满足则将bean加入到三级缓存中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 属性注入 populateBean(beanName, mbd, instanceWrapper); // 初始化bean exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set
何时放入二级缓存?
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) { // 从三级缓存找到相关引用后,将其提升至二级缓存,并且删除三级缓存 singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
为什么需要二级缓存?
因为在加入三级缓存时,需要调用getEarlyBeanReference方法
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
这里等价于:
addSingletonFactory(beanName, new ObjectFactory() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, 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; // 调用各个bean的后置处理器的getEarlyBeanReference exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; }
第二个原因:使用三级缓存而非二级缓存并不是因为只有三级缓存才能解决循环引用问题,其实二级缓存同样也能很好解决循环引用问题。使用三级而非二级缓存并非出于IOC的考虑,而是出于AOP的考虑,即若使用二级缓存,在AOP情形下,注入到其他bean的,不是最终的代理对象,而是原始对象。
上文我们提到过,通过工厂去获取引用,需要遍历后置处理器,每个处理器还需要调用getEarlyBeanReference,而AOP的后置处理器:AbstractAutoProxyCreator
public Object getEarlyBeanReference(Object bean, String beanName) { Object cacheKey = this.getCacheKey(bean.getClass(), beanName); this.earlyProxyReferences.put(cacheKey, bean); // 调用后返回的是指定bean的代理对象 return this.wrapIfNecessary(bean, beanName, cacheKey); }
AbstractAutoProxyCreator#getEarlyBeanReference返回的是代理对象,所以exposedObject暴露对象也是代理对象而不是原始对象,所以如果只使用二级缓存,不使用三级缓存的话,注入到其他bean的将是原始对象,而不是代理对象
参考:
Spring系列:Spring循环依赖知多少?(不一样的深度分析)
曹工说Spring Boot源码(29)-- Spring 解决循环依赖为什么使用三级缓存,而不是二级缓存
2.4 bean实例化过程
接着上面bean循环依赖的处理关于第三级缓存何时放入,继续聊bean的实例化过程,上面在看放入第三级缓存的方法中:doCreateBean其实里边就包含了实例创建的过程。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 解析bean的class类型 Class> beanClass = resolveBeanClass(mbd, beanName); // 确保bean的class是public if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } Supplier> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 工厂方法实例化 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器 // 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析 boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { return instantiateBean(beanName, mbd); } } // Candidate constructors for autowiring? Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // Preferred constructors for default construction? ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); }
上面代码非常长,总体的功能逻辑如下:
确定参数。
如果调用getBean方式时传入的参数不为空,则可以直接使用传入的参数;再尝试从缓存中获取参数否则,需要解析配置节点时,配置的构造器参数。
**确定构造函数。**根据第一步中确定下来的参数,接下来的任务就是根据参数的个数、类型来确定最终调用的构造函数。首先是根据参数个数匹配,把所有构造函数根据参数个数升序排序,再去筛选参数个数匹配的构造函数;因为配置文件中可以通过参数位置索引,也可以通过参数名称来设定参数值,如
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { Object beanInstance; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged( (PrivilegedAction
最后看到的调用时BeanUtils中的反射方法完成实例化或者通过CGLIB生成代理对象
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (!bd.hasMethodOverrides()) { Constructor> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction
实例化bean是通过BeanUtils中的方法通过反射实例化出Bean
public static
CGLIB生成代理对象
public Object instantiate(@Nullable Constructor> ctor, Object... args) { Class> subclass = createEnhancedSubclass(this.beanDefinition); Object instance; if (ctor == null) { instance = BeanUtils.instantiateClass(subclass); } else { try { Constructor> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes()); instance = enhancedSubclassConstructor.newInstance(args); } catch (Exception ex) { throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex); } } // SPR-10785: set callbacks directly on the instance instead of in the // enhanced class (via the Enhancer) in order to avoid memory leaks. Factory factory = (Factory) instance; factory.setCallbacks(new Callback[] {NoOp.INSTANCE, new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner), new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)}); return instance; }
整一个调用链路:
createBeanInstance |instantiateBean(beanName, mbd) |beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this) |BeanUtils.instantiateClass(constructorToUse)
2.5 代理对象生成
spring有非常多的地方都是使用代理的,但是这些什么使用代理,使用哪种代理,代理是在什么时候创建的,怎么运行起效的。
spring的代理创建类都是AbstractAutoProxyCreator的子类,这个抽象类同时又是InstantiationAwareBeanPostProcessor的实现类。 由于它是BeanPostProcessor的实现类,下面的两个方法就非常重要:
初始化前方法:
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // 创建代理对象 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
创建代理:AbstractAutoProxyCreator#createProxy
protected Object createProxy(Class> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 通过代理工厂创建代理 return proxyFactory.getProxy(getProxyClassLoader()); } public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
ProxyFactory#getProxy他是ProxyCreatorSupport的子类,ProxyCreatorSupport定义了代理对象的生成方法:
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
通过代理工厂生产代理AopProxyFactory:
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } // 如果目标类实现接口则使用JDK动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); }// 否则使用CGLIB实现动态代理 return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
JDK动态代理:
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified"); } this.advised = config; } @Override public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } @Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // 底层还是Proxy对象的newProxyInstance方法 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
JDK和CGILB动态代理原理补充:
JDK动态代理关键实现方法解析:
调用 getProxyClass0() 方法获取代理类的 Class 对象通过反射生成 代理类的实例,并返回。
public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } // 调用 getProxyClass0() 方法获取代理类的 Class 对象 Class> cl = getProxyClass0(loader, intfs); try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } // 通过反射生成 代理类的实例,并返回。 final Constructor> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction
生成代理类:
private static final class ProxyClassFactory implements BiFunction
所以,JDK动态代理是通过生成代理类的字节码,然后利用classloader动态加载字节码生成动态代理类的class实例
CGLIB动态代理:
CGLIB生成的代理类是目标类的子类,通过子类实现对目标类的增强,底层是通过ASM字节码框架操作字节码实现。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~