Spring源码解析(四)Bean的实例化和依赖注入
我们虽然获得了Bean的描述信息BeanDefinition,但是什么时候才会真正的实例化这些Bean呢。其实一共有两个触发点,但是最后实际上调用的是同一个方法。
第一个:在AbstractApplicationContext的refresh()方法中,容器会初始化lazy-init=false的bean。
- // Instantiate all remaining (non-lazy-init) singletons.
- finishBeanFactoryInitialization(beanFactory);
第二个:在获得了ApplicationContext后,调用getBean(XX)方法。
实际上它们最终都是调用的AbstractBeanFactory的doGetBean(XX)方法。
- /**
- * Return an instance, which may be shared or independent, of the specified bean.
- * @param name the name of the bean to retrieve
- * @param requiredType the required type of the bean to retrieve
- * @param args arguments to use if creating a prototype using explicit arguments to a
- * static factory method. It is invalid to use a non-null args value in any other case.
- * @param typeCheckOnly whether the instance is obtained for a type check,
- * not for actual use
- * @return an instance of the bean
- * @throws BeansException if the bean could not be created
- */
- @SuppressWarnings("unchecked")
- protected <T> T doGetBean(
- final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
- throws BeansException {
- //如果name已&开头,去掉&
- final String beanName = transformedBeanName(name);
- Object bean;
- // Eagerly check singleton cache for manually registered singletons.
- /**1.先在单例缓存中查找*/
- Object sharedInstance = getSingleton(beanName);
- if (sharedInstance != null && args == null) {
- if (logger.isDebugEnabled()) {
- if (isSingletonCurrentlyInCreation(beanName)) {
- logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
- "' that is not fully initialized yet - a consequence of a circular reference");
- }
- else {
- logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
- }
- }
- /**2.判断返回instance本身还是要返回FacotryBean*/
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
- }
- else {
- // Fail if we're already creating this bean instance:
- // We're assumably within a circular reference.
- //判断是否不是循环引用
- if (isPrototypeCurrentlyInCreation(beanName)) {
- throw new BeanCurrentlyInCreationException(beanName);
- }
- // Check if bean definition exists in this factory.
- BeanFactory parentBeanFactory = getParentBeanFactory();
- if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
- // Not found -> check parent.
- String nameToLookup = originalBeanName(name);
- if (args != null) {
- // Delegation to parent with explicit args.
- return (T) parentBeanFactory.getBean(nameToLookup, args);
- }
- else {
- // No args -> delegate to standard getBean method.
- return parentBeanFactory.getBean(nameToLookup, requiredType);
- }
- }
- //标记bean已被创建
- if (!typeCheckOnly) {
- markBeanAsCreated(beanName);
- }
- try {
- final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
- checkMergedBeanDefinition(mbd, beanName, args);
- // Guarantee initialization of beans that the current bean depends on.
- /**3.如果bean依赖于其他bean先初始化,先初始化依赖的bean*/
- String[] dependsOn = mbd.getDependsOn();
- if (dependsOn != null) {
- for (String dependsOnBean : dependsOn) {
- getBean(dependsOnBean);
- /**4.记录两个bean相互依赖关系,被依赖的bean在销毁前,要先要销毁依赖它的bean*/
- registerDependentBean(dependsOnBean, beanName);
- }
- }
- // Create bean instance.
- /**
- * 5.创建单例bean,scope="singleton"
- */
- if (mbd.isSingleton()) {
- sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
- public Object getObject() throws BeansException {
- try {
- return createBean(beanName, mbd, args);
- }
- catch (BeansException ex) {
- // Explicitly remove instance from singleton cache: It might have been put there
- // eagerly by the creation process, to allow for circular reference resolution.
- // Also remove any beans that received a temporary reference to the bean.
- destroySingleton(beanName);
- throw ex;
- }
- }
- });
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
- }
- /**
- * 6.创建原型bean,scope="prototype"
- */
- else if (mbd.isPrototype()) {
- // It's a prototype -> create a new instance.
- Object prototypeInstance = null;
- try {
- beforePrototypeCreation(beanName);
- prototypeInstance = createBean(beanName, mbd, args);
- }
- finally {
- afterPrototypeCreation(beanName);
- }
- bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
- }
- /**
- * 7. scope=request/session/globalSession
- */
- else {
- String scopeName = mbd.getScope();
- final Scope scope = this.scopes.get(scopeName);
- if (scope == null) {
- throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
- }
- try {
- Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
- public Object getObject() throws BeansException {
- beforePrototypeCreation(beanName);
- try {
- return createBean(beanName, mbd, args);
- }
- finally {
- afterPrototypeCreation(beanName);
- }
- }
- });
- bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
- }
- catch (IllegalStateException ex) {
- throw new BeanCreationException(beanName,
- "Scope '" + scopeName + "' is not active for the current thread; " +
- "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
- ex);
- }
- }
- }
- catch (BeansException ex) {
- cleanupAfterBeanCreationFailure(beanName);
- throw ex;
- }
- }
- // Check if required type matches the type of the actual bean instance.
- if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
- try {
- return getTypeConverter().convertIfNecessary(bean, requiredType);
- }
- catch (TypeMismatchException ex) {
- if (logger.isDebugEnabled()) {
- logger.debug("Failed to convert bean '" + name + "' to required type [" +
- ClassUtils.getQualifiedName(requiredType) + "]", ex);
- }
- throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
- }
- }
- return (T) bean;
- }
AbstractAutowireCapableBeanFactory的createBean方法:
- @Override
- protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
- throws BeanCreationException {
- if (logger.isDebugEnabled()) {
- logger.debug("Creating instance of bean '" + beanName + "'");
- }
- // Make sure bean class is actually resolved at this point.
- /**1.解析Bean的Class*/
- resolveBeanClass(mbd, beanName);
- // Prepare method overrides.
- try {
- /**2.方法注入准备*/
- mbd.prepareMethodOverrides();
- }
- catch (BeanDefinitionValidationException ex) {
- throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
- beanName, "Validation of method overrides failed", ex);
- }
- try {
- // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
- /**3.BeanPostProcesser第一个扩展点,可以返回一个代理类*/
- Object bean = resolveBeforeInstantiation(beanName, mbd);
- if (bean != null) {
- return bean;
- }
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "BeanPostProcessor before instantiation of bean failed", ex);
- }
- /**4.执行spring创建bena实例的流程*/
- Object beanInstance = doCreateBean(beanName, mbd, args);
- if (logger.isDebugEnabled()) {
- logger.debug("Finished creating instance of bean '" + beanName + "'");
- }
- return beanInstance;
- }
第4步才是真正创建实例和初始化的主要方法:
- protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
- // Instantiate the bean.
- BeanWrapper instanceWrapper = null;
- if (mbd.isSingleton()) {
- instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
- }
- if (instanceWrapper == null) {
- /**5.创建bean实例*/
- instanceWrapper = createBeanInstance(beanName, mbd, args);
- }
- final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
- Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
- // Allow post-processors to modify the merged bean definition.
- /**
- * 6.MergedBeanDefinitionPostProcessor合并父子类属性,例如:List属性
- */
- synchronized (mbd.postProcessingLock) {
- if (!mbd.postProcessed) {
- applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
- mbd.postProcessed = true;
- }
- }
- // Eagerly cache singletons to be able to resolve circular references
- // even when triggered by lifecycle interfaces like BeanFactoryAware.
- /**
- * 7.及早暴露单例bean引用,解决循环引用
- */
- boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
- isSingletonCurrentlyInCreation(beanName));
- if (earlySingletonExposure) {
- if (logger.isDebugEnabled()) {
- logger.debug("Eagerly caching bean '" + beanName +
- "' to allow for resolving potential circular references");
- }
- //创建匿名内部类,匿名内部类会讲beanName、mbd,bean(final修饰)拷贝一份到内部类,已保证当前方法执行完成后局部变量退栈后内部类还可以访问。
- addSingletonFactory(beanName, new ObjectFactory<Object>() {
- public Object getObject() throws BeansException {
- return getEarlyBeanReference(beanName, mbd, bean);
- }
- });
- }
- // Initialize the bean instance.
- Object exposedObject = bean;
- try {
- /**
- * 8.依赖注入
- */
- populateBean(beanName, mbd, instanceWrapper);
- if (exposedObject != null) {
- /**
- * 9.执行自定义BeanProcesser和init-method
- */
- 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<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
- for (String dependentBean : dependentBeans) {
- if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
- actualDependentBeans.add(dependentBean);
- }
- }
- if (!actualDependentBeans.isEmpty()) {
- throw new BeanCurrentlyInCreationException(beanName,
- "Bean with name '" + beanName + "' has been injected into other beans [" +
- StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
- "] in its raw version as part of a circular reference, but has eventually been " +
- "wrapped. This means that said other beans do not use the final version of the " +
- "bean. This is often the result of over-eager type matching - consider using " +
- "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
- }
- }
- }
- }
- // Register bean as disposable.
- try {
- /**
- * 10.注册DestructionAwareBeanPostProcessors和destroy-method
- */
- registerDisposableBeanIfNecessary(beanName, bean, mbd);
- }
- catch (BeanDefinitionValidationException ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
- }
- return exposedObject;
- }
第5步:实例化Bean对象,封装成BeanWrapper
- protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
- // Make sure bean class is actually resolved at this point.
- Class<?> beanClass = resolveBeanClass(mbd, beanName);
- 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());
- }
- /**5.1 通过静态方法来实例化bean*/
- if (mbd.getFactoryMethodName() != null) {
- return instantiateUsingFactoryMethod(beanName, mbd, args);
- }
- // Shortcut when re-creating the same bean...
- boolean resolved = false;
- boolean autowireNecessary = false;
- if (args == null) {
- synchronized (mbd.constructorArgumentLock) {
- if (mbd.resolvedConstructorOrFactoryMethod != null) {
- resolved = true;
- autowireNecessary = mbd.constructorArgumentsResolved;
- }
- }
- }
- /**5.2 暂时不知道什么时候会走这???????*/
- if (resolved) {
- if (autowireNecessary) {
- return autowireConstructor(beanName, mbd, null, null);
- }
- else {
- return instantiateBean(beanName, mbd);
- }
- }
- // Need to determine the constructor...
- /**5.3 BeanPostProcessor的又一个扩展点:SmartInstantiationAwareBeanPostProcessor。
- * 检测Bean的构造器,可以检测出多个候选构造器,再有相应的策略决定使用哪一个,
- * 如AutowiredAnnotationBeanPostProcessor实现将自动扫描通过@Autowired/@Va
- */
- Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
- /**5.4 通过构造器实例化bean,包括autowire=constructor 和<constructor-arg></constructor-arg>*/
- if (ctors != null ||
- mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
- mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
- return autowireConstructor(beanName, mbd, ctors, args);
- }
- // No special handling: simply use no-arg constructor.
- /**5.5 通过无参构造器实例化bean*/
- return instantiateBean(beanName, mbd);
- }
第8步:Bean实例的初始化也就是属性的注入
- /**
- * Populate the bean instance in the given BeanWrapper with the property values
- * from the bean definition.
- * @param beanName the name of the bean
- * @param mbd the bean definition for the bean
- * @param bw BeanWrapper with bean instance
- */
- protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
- PropertyValues pvs = mbd.getPropertyValues();
- if (bw == null) {
- if (!pvs.isEmpty()) {
- throw new BeanCreationException(
- mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
- }
- else {
- // Skip property population phase for null instance.
- return;
- }
- }
- // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
- // state of the bean before properties are set. This can be used, for example,
- // to support styles of field injection.
- boolean continueWithPropertyPopulation = true;
- /**
- * 扩展点3:通过InstantiationAwareBeanPostProcessor给属性赋值
- */
- if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
- for (BeanPostProcessor bp : getBeanPostProcessors()) {
- if (bp instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
- if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
- continueWithPropertyPopulation = false;
- break;
- }
- }
- }
- }
- if (!continueWithPropertyPopulation) {
- return;
- }
- if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
- mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
- MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
- // Add property values based on autowire by name if applicable.
- if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
- //根据Name自动装配
- autowireByName(beanName, mbd, bw, newPvs);
- }
- // Add property values based on autowire by type if applicable.
- if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
- //根据Type自动装配
- autowireByType(beanName, mbd, bw, newPvs);
- }
- pvs = newPvs;
- }
- boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
- boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
- if (hasInstAwareBpps || needsDepCheck) {
- PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
- if (hasInstAwareBpps) {
- /**
- * InstantiationAwareBeanPostProcesser在属性注入之前的扩展点
- */
- for (BeanPostProcessor bp : getBeanPostProcessors()) {
- if (bp instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
- pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
- if (pvs == null) {
- return;
- }
- }
- }
- }
- /**是否需要依赖检查*/
- if (needsDepCheck) {
- checkDependencies(beanName, mbd, filteredPds, pvs);
- }
- }
- /**属性注入*/
- applyPropertyValues(beanName, mbd, bw, pvs);
- }
最终是通过java反射调用set方法的invoke实现的属性注入。BeanWrapperImpl setPropertyValue方法
- //省略..... if (System.getSecurityManager() != null) {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- writeMethod.invoke(object, value);
- return null;
- }
- }, acc);
- }
- catch (PrivilegedActionException ex) {
- throw ex.getException();
- }
- }
- else {
- writeMethod.invoke(this.object, value);
- }
- }
- //省略.....
到此,bean的实例化和属性注入已经完成。但是Bean实例的初始化工作还没完成,还有一系列的初始化工作。
第9步:初始化Bean实例
- protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
- if (System.getSecurityManager() != null) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- invokeAwareMethods(beanName, bean);
- return null;
- }
- }, getAccessControlContext());
- }
- else {
- /**1.为实现Aware接口的bean设置一些相应的资源**/
- invokeAwareMethods(beanName, bean);
- }
- Object wrappedBean = bean;
- if (mbd == null || !mbd.isSynthetic()) {
- /**2.调用BeanPostProcesser postProcessBeforeInitialization方法*/
- wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
- }
- try {
- /**3.调用InitializingBean的afterPropertiesSet方法
- * 调用自定义init-method
- */
- invokeInitMethods(beanName, wrappedBean, mbd);
- }
- catch (Throwable ex) {
- throw new BeanCreationException(
- (mbd != null ? mbd.getResourceDescription() : null),
- beanName, "Invocation of init method failed", ex);
- }
- if (mbd == null || !mbd.isSynthetic()) {
- /**
- * 4.调用BeanPostProcesser postProcessAfterInitialization方法
- */
- wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
- }
- return wrappedBean;
- }
第10步:注册DisposableBean
- protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
- AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
- if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
- //单例
- if (mbd.isSingleton()) {
- // Register a DisposableBean implementation that performs all destruction
- // work for the given bean: DestructionAwareBeanPostProcessors,
- // DisposableBean interface, custom destroy method.
- registerDisposableBean(beanName,
- new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
- }
- else {
- // A bean with a custom scope...
- Scope scope = this.scopes.get(mbd.getScope());
- if (scope == null) {
- throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");
- }
- scope.registerDestructionCallback(beanName,
- new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
- }
- }
- }
- public void registerDisposableBean(String beanName, DisposableBean bean) {
- synchronized (this.disposableBeans) {
- this.disposableBeans.put(beanName, bean);
- }
- }
- public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
- List<BeanPostProcessor> postProcessors, AccessControlContext acc) {
- Assert.notNull(bean, "Disposable bean must not be null");
- this.bean = bean;
- this.beanName = beanName;
- this.invokeDisposableBean =
- (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
- this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
- this.acc = acc;
- String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
- if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
- !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
- this.destroyMethodName = destroyMethodName;
- this.destroyMethod = determineDestroyMethod();
- if (this.destroyMethod == null) {
- if (beanDefinition.isEnforceDestroyMethod()) {
- throw new BeanDefinitionValidationException("Couldn't find a destroy method named '" +
- destroyMethodName + "' on bean with name '" + beanName + "'");
- }
- }
- else {
- Class<?>[] paramTypes = this.destroyMethod.getParameterTypes();
- if (paramTypes.length > 1) {
- throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
- beanName + "' has more than one parameter - not supported as destroy method");
- }
- else if (paramTypes.length == 1 && !paramTypes[0].equals(boolean.class)) {
- throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
- beanName + "' has a non-boolean parameter - not supported as destroy method");
- }
- }
- }
- this.beanPostProcessors = filterPostProcessors(postProcessors);
- }
到此,Spring Bean的实例化和初始化工作就完成了。
总结一下Bean的实例创建和初始化过程,也就是Bean的生命周期:
Spring源码解析(四)Bean的实例化和依赖注入的更多相关文章
- Spring源码解析三:IOC容器的依赖注入
一般情况下,依赖注入的过程是发生在用户第一次向容器索要Bean是触发的,而触发依赖注入的地方就是BeanFactory的getBean方法. 这里以DefaultListableBeanFactory ...
- Spring源码解析——循环依赖的解决方案
一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...
- Spring源码-IOC部分-Bean实例化过程【5】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...
- Spring 源码分析之 bean 依赖注入原理(注入属性)
最近在研究Spring bean 生命周期相关知识点以及源码,所以打算写一篇 Spring bean生命周期相关的文章,但是整理过程中发现涉及的点太多而且又很复杂,很难在一篇文章中把Spri ...
- Spring源码解析 - AbstractBeanFactory 实现接口与父类分析
我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...
- Spring源码分析之Bean的创建过程详解
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...
- spring 源码解析
1. [文件] spring源码.txt ~ 15B 下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB 下载( ...
- Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?
Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的? 如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...
- Spring源码解析之BeanFactoryPostProcessor(三)
在上一章中笔者介绍了refresh()的<1>处是如何获取beanFactory对象,下面我们要来学习refresh()方法的<2>处是如何调用invokeBeanFactor ...
随机推荐
- Unity UI大小动态设置(Resize Unity UI RectTransform)
我们在开发过程中发现,要调整Unity UI元素的大小,RectTransform提供了sizeDelta属性可以用来动态修改RectTransform的大小,但同时我们也google到另外一个修改R ...
- 【java】java 设计模式(4):建造者模式(Builder)
工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性,其实建造者模式就是前面抽象工厂模式和最后的Test结合起来得到 ...
- java socket通信-传输文件图片--传输图片
ClientTcpSend.java client发送类 package com.yjf.test; import java.io.DataOutputStream; import java.io ...
- 京东云擎”本周四推出一键免费安装Discuz论坛
“京东云擎”本周四推出一键免费安装Discuz论坛了,让用户能在1分钟之内建立自己的论坛.这是继上周云擎推出一键安装WordPress之后的又一重大免费贡献! 云擎: http://jae.jd.co ...
- Android DOM解析XML示例程序
DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的.DOM比较符合人的思维模式,但是其对内存的消耗比较大. activity_main.xml < ...
- 编写一个读写倾斜测量数据.s3c文件格式的OSG插件osgdb_s3c
VS新建一个空的DLL工程 ReaderWriterS3C.cpp源文件 #include <osg/Notify> #include <osgDB/FileNameUtils> ...
- 你知道嵌入式C语言中各变量存储的位置吗?
局部变量.局部静态变量.全局变量.全局静态变量区别如下: 局部变量: 栈区: 局部静态变量:静态区: 全局变量: 静态区的常量区: 全局静态变量:静态区. 在进行C/C++编程时,需要程序员对内存的了 ...
- 使用fetch-jsonp进行跨域以及参数的传递
其实fetch-jsonp的官方文档里面已经写得很详细了,连接如下:https://github.com/camsong/fetch-jsonp:但是由于它本身没有多少demo,所以自己在上手的时候遇 ...
- django实现瀑布流、组合搜索、阶梯评论、验证码
django实现图片瀑布流布局 我们在一些图片网站上经常会看到,满屏都是图片,而且图片都大小不一,却可以按空间排列.默认一个div是占用一行,当想把div里的图片并排显示的时候,只能使用float属性 ...
- poj_2774 后缀数组
题目大意 给定两个字符串A,B,求出A和B中最长公共子串的长度. 题目分析 字符串的子串可以认为是是字符串的某个后缀的前缀,而求最长公共子串相当于A和B的某两个后缀的最长相同前缀.可以考虑使用后缀数组 ...