Spring IoC (Inversion of Control,控制反转)是Spring框架的核心概念之一,它是一种设计模式,用于解耦组件之间的依赖关系,提供更灵活、可维护和可测试的代码。IoC的主要思想是,将对象的创建和依赖关系的管理交给容器来处理,而不是由对象自身来创建和管理依赖
IoC(Inversion of Control)控制反转 :所谓控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。这个描述最具体的表现就是我们看到的配置文件,或者是注解
DI(Dependency Injection)依赖注入 :就是指对象被动接受依赖类而不是自己主动去找,换句话说就是指对象不是从容器中查找它依赖的类了,而是在容器实例化对象的时候主动将它依赖的类注入给它
在传统的编程中,一个对象通常负责创建其依赖的其他对象,这导致了高度耦合的代码,难以修改和维护。通过使用IoC,我们将控制权转移到框架(或容器)中,框架负责创建和管理对象的实例,并将它们注入到需要它们的组件中
Spring IoC的主要组件是Bean容器,它负责实例化、配置和管理Bean(对象)。Bean
是Spring框架中的核心组件,它们是由Spring容器创建和管理的普通Java对象。
Spring IoC的实现方式有两种:基于XML配置和基于注解配置
Spring容器启动 最基本的启动 Spring 容器的例子:
1 2 3 public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("classpath:applicationfile.xml" ); }
ApplicationContext context = new ClassPathXmlApplicationContext(...)
从名字上就可以看出来,就是在 ClassPath 中寻找 xml 配置文件,根据 xml 文件内容来构建 ApplicationContext
。当然,除了 ClassPathXmlApplicationContext
以外,我们也还有其他构建 ApplicationContext
的方案可供选择
ClassPathXmlApplicationContext
的构造函数:
1 2 3 public ClassPathXmlApplicationContext (String configLocation) throws BeansException { this (new String [] {configLocation}, true , null ); }
实际调用的构造函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 public ClassPathXmlApplicationContext ( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super (parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
还有像 AnnotationConfigApplicationContext
、FileSystemXmlApplicationContext
、XmlWebApplicationContext
等都继承自父容器 AbstractApplicationContext
主要用到了装饰器模式和策略模式,最终都是调用 refresh() 方法
AbstractApplicationContext#refresh
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 @Override public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { StartupStep contextRefresh = this .applicationStartup.start("spring.context.refresh" ); prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this .applicationStartup.start("spring.context.beans.post-process" ); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); beanPostProcess.end(); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); contextRefresh.end(); } } }
refresh()
方法是在应用程序上下文(ApplicationContext )启动过程中的一个重要方法。它的主要作用是刷新应用程序上下文,也就是启动Spring容器并完成初始化过程,使得容器准备好处理请求和提供Bean实例。它在以下情况下被调用:
Spring容器启动时,refresh()
方法会在容器初始化时调用,用于创建和初始化所有注册的Bean。
在热加载(hot reloading )场景中,当类文件或配置文件发生变化时,可以手动调用refresh()
方法来重新加载 ApplicationContext
,实现动态更新应用程序上下文。
refresh()
方法的执行过程包括以下主要步骤:
调用prepareRefresh()
方法:在刷新之前执行的预处理,通常用于初始化容器的状态
调用obtainFreshBeanFactory()
方法:创建或获取一个新的BeanFactory实例,这是整个IOC容器的核心。它负责Bean的注册、依赖注入等工作
调用prepareBeanFactory(beanFactory)
方法:对BeanFactory进行一些设置,如注册后置处理器、添加属性编辑器等
调用postProcessBeanFactory(beanFactory)
方法:允许子类在标准初始化后对BeanFactory进行进一步的定制
调用invokeBeanFactoryPostProcessors(beanFactory)
方法:调用所有注册的BeanFactory后置处理器,这些后置处理器可以修改或添加BeanFactory中的Bean定义
调用registerBeanPostProcessors(beanFactory)
方法:注册所有的Bean后置处理器,这些后置处理器会在Bean的初始化过程中添加额外的逻辑
调用initMessageSource()
方法:初始化消息资源,用于国际化支持
调用initApplicationEventMulticaster()
方法:初始化事件广播器,用于处理应用程序事件
调用onRefresh()
方法:在刷新过程中的回调方法,允许子类执行自定义的刷新逻辑
调用registerListeners()
方法:注册应用程序事件监听器
调用finishBeanFactoryInitialization(beanFactory)
方法:完成剩余的Bean初始化工作,包括实例化非懒加载的单例Bean
调用finishRefresh()
方法:在刷新过程完成后执行的回调方法
完成刷新过程,容器准备好接收请求并提供Bean实例
refresh()
方法里反复提到了一个类:BeanFactory
,下面先解释一下 BeanFactory
是什么
BeanFactory BeanFactory,从名字上也很好理解,生产 bean 的工厂,它负责生产和管理各个 bean 实例。BeanFactory 在 Spring 中是一个核心接口,它是IOC容器的基础,负责创建、管理和查找Bean对象。BeanFactory定义了访问Spring容器中Bean的标准方法,提供了IOC容器的基本功能
ApplicationContext
继承了 ListableBeanFactory
,这个 Listable 的意思就是,通过这个接口可以获取多个 Bean
ApplicationContext
继承了 HierarchicalBeanFactory
,Hierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系
AutowireCapableBeanFactory
这个名字中的 Autowire
表明它就是用来自动装配 Bean 用的,虽然ApplicationContext
并没有继承它,但是可以通过组合的方法:ApplicationContext
接口定义中的最后一个方法 getAutowireCapableBeanFactory()
ConfigurableListableBeanFactory
也是一个特殊的接口,在于它继承了第二层所有的三个接口,而 ApplicationContext
没有
refresh() 再回头来说 refresh()
方法,从上到下依次:
prepareRefresh()
创建 Bean 容器前的准备工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 protected void prepareRefresh () { this .startupDate = System.currentTimeMillis(); this .closed.set(false ); this .active.set(true ); ... getEnvironment().validateRequiredProperties(); ... }
obtainFreshBeanFactory()
初始化 BeanFactory,加载 Bean、注册 Bean:
1 2 3 4 protected ConfigurableListableBeanFactory obtainFreshBeanFactory () { refreshBeanFactory(); return getBeanFactory(); }
AbstractRefreshableApplicationContext#refreshBeanFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override protected final void refreshBeanFactory () throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); this .beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException ("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
这里创建了一个 DefaultListableBeanFactory
实例,从之前的图上看得出,DefaultListableBeanFactory
实现了 ListableBeanFactory
,HierarchicalBeanFactory
和 AutowireCapableBeanFactory
,是功能最全面的 beanFactory
beanFactory 说了那么久,他是个 bean 的容器,那么 bean 是什么?bean 在代码层面上可以认为是 beanDefinition 的实例。beanDefinition 中保存了 bean 的信息
beanDefinition
的接口定义:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 public interface BeanDefinition extends AttributeAccessor , BeanMetadataElement { String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; int ROLE_APPLICATION = 0 ; int ROLE_SUPPORT = 1 ; int ROLE_INFRASTRUCTURE = 2 ; void setParentName (String parentName) ; String getParentName () ; void setBeanClassName (String beanClassName) ; String getBeanClassName () ; void setLazyInit (boolean lazyInit) ; boolean isLazyInit () ; void setDependsOn (String... dependsOn) ; String[] getDependsOn(); void setAutowireCandidate (boolean autowireCandidate) ; void setPrimary (boolean primary) ; void setFactoryBeanName (String factoryBeanName) ; String getFactoryBeanName () ; void setFactoryMethodName (String factoryMethodName) ; String getFactoryMethodName () ; ConstructorArgumentValues getConstructorArgumentValues () ; MutablePropertyValues getPropertyValues () ; boolean isSingleton () ; boolean isPrototype () ; boolean isAbstract () ; int getRole () ; String getDescription () ; String getResourceDescription () ; BeanDefinition getOriginatingBeanDefinition () ; }
customizeBeanFactory(beanFactory)
1 2 3 4 5 6 7 8 protected void customizeBeanFactory (DefaultListableBeanFactory beanFactory) { if (this .allowBeanDefinitionOverriding != null ) { beanFactory.setAllowBeanDefinitionOverriding(this .allowBeanDefinitionOverriding); } if (this .allowCircularReferences != null ) { beanFactory.setAllowCircularReferences(this .allowCircularReferences); } }
配置是否允许 beanDefinition
覆盖、是否允许循环引用
loadBeanDefinitions(beanFactory)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Override protected void loadBeanDefinitions (DefaultListableBeanFactory beanFactory) throws BeansException, IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader (beanFactory); beanDefinitionReader.setEnvironment(this .getEnvironment()); beanDefinitionReader.setResourceLoader(this ); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver (this )); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
prepareBeanFactory(beanFactory)
把在 xml 配置的 bean 都注册以后,会”手动”注册一些特殊的 bean。
这里简单介绍下 prepareBeanFactory(factory) 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 protected void prepareBeanFactory (ConfigurableListableBeanFactory beanFactory) { beanFactory.setBeanClassLoader(getClassLoader()); if (!shouldIgnoreSpel) { beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver (beanFactory.getBeanClassLoader())); } beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar (this , getEnvironment())); beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor (this )); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class); beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this ); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this ); beanFactory.registerResolvableDependency(ApplicationContext.class, this ); ... if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) { beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup()); } }
…
finishBeanFactoryInitialization(beanFactory)
负责初始化所有的 singleton beans。到目前为止,应该说 BeanFactory 已经创建完成,并且所有的实现了 BeanFactoryPostProcessor 接口的 Bean 都已经初始化并且其中的 postProcessBeanFactory(factory)
方法已经得到回调执行了。而且 Spring 已经“手动”注册了一些特殊的 Bean,如 environment
、systemProperties
等
剩下的就是初始化 singleton beans 了,我们知道它们是单例的,如果没有设置懒加载,那么 Spring 会在接下来初始化所有的 singleton beans
1 2 3 4 5 6 7 8 9 10 11 12 13 protected void finishBeanFactoryInitialization (ConfigurableListableBeanFactory beanFactory) { if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } ... beanFactory.preInstantiateSingletons(); }
preInstantiateSingletons()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Override public void preInstantiateSingletons () throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this ); } List<String> beanNames = new ArrayList <>(this .beanDefinitionNames); for (String beanName : beanNames) { ... getBean(beanName); ... } }
getBean()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 @Override public Object getBean (String name) throws BeansException { return doGetBean(name, null , null , false ); }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; Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null ) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("..." ); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'" ); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null ); } else { if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException (beanName); } BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null ) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null ) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException (mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'" ); } registerDependentBean(dep, beanName); getBean(dep); } } if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory <Object>() { @Override public Object getObject () throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { Object prototypeInstance = null ; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this .scopes.get(scopeName); if (scope == null ) { throw new IllegalStateException ("No Scope registered for scope name '" + scopeName + "'" ); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory <Object>() { @Override 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; } } if (requiredType != null && bean != null && !requiredType.isInstance(bean)) { 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; }
然后是createBean()
AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @Override protected Object createBean (String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'" ); } RootBeanDefinition mbdToUse = mbd; Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null ) { mbdToUse = new RootBeanDefinition (mbd); mbdToUse.setBeanClass(resolvedClass); } try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException (mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed" , ex); } try { Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null ) { return bean; } } catch (Throwable ex) { throw new BeanCreationException (mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed" , ex); } Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'" ); } return beanInstance; }
AbstractAutowireCapableBeanFactory#doCreateBean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 protected Object doCreateBean (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null ; if (mbd.isSingleton()) { instanceWrapper = this .factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null ) { instanceWrapper = createBeanInstance(beanName, mbd, args); } ... boolean earlySingletonExposure = (mbd.isSingleton() && this .allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references" ); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } ... return exposedObject; }
基于Annotation的IoC初始化 Annotation 从Spring2.0以后的版本中,Spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5中引入的一个新特性,用于简化Bean的配置,可以取代XML配置文件。开发人员对注解(Annotation)的态度也是萝卜白菜各有所爱,个人认为注解可以简化配置,提高开发速度,但也给后期维护增加了难度。随着Spring Boot的兴起,基于注解的开发甚至实现了零配置。Spring IOC容器对于类级别的注解和类内部的注解分一下两种处理策略:
类级别的注解:@Component
、@Repository
、@Controller
、@Service
以及JavaEE6的@ManagedBean
和@Named
注解,都是添加在类上面的类级别注解,Spring容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到Spring IOC容器中。
类内部的注解:@Autowire
、@Value
、@Resource
以及EJB和WebService相关的注解等,都是添加在类内部的字段或者方法上的类内部注解,Spring IOC容器通过Bean后置注解处理器解析Bean内部的注解。
定位Bean扫描路径 在Spring中管理注解Bean定义的容器有两个:AnnotationConfigApplicationContext
和AnnotationConfigWebApplicationContext
。这两个类的专门处理Spring注解方式配置的容器,直接依赖于注解作为容器配置信息来源的IOC容器。AnnotationConfigWebApplicationContext
是 AnnotationConfigApplicationContext
的Web版本,两者的用法以及对注解的处理方式几乎没有差别。现在我们以 AnnotationConfigApplicationContext
为例看它的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { private final AnnotatedBeanDefinitionReader reader; private final ClassPathBeanDefinitionScanner scanner; public AnnotationConfigApplicationContext () { this .reader = new AnnotatedBeanDefinitionReader (this ); this .scanner = new ClassPathBeanDefinitionScanner (this ); } public AnnotationConfigApplicationContext (DefaultListableBeanFactory beanFactory) { super (beanFactory); this .reader = new AnnotatedBeanDefinitionReader (this ); this .scanner = new ClassPathBeanDefinitionScanner (this ); } public AnnotationConfigApplicationContext (Class<?>... annotatedClasses) { this (); register(annotatedClasses); refresh(); } public AnnotationConfigApplicationContext (String... basePackages) { this (); scan(basePackages); refresh(); } @Override public void setEnvironment (ConfigurableEnvironment environment) { super .setEnvironment(environment); this .reader.setEnvironment(environment); this .scanner.setEnvironment(environment); } public void setBeanNameGenerator (BeanNameGenerator beanNameGenerator) { this .reader.setBeanNameGenerator(beanNameGenerator); this .scanner.setBeanNameGenerator(beanNameGenerator); getBeanFactory().registerSingleton( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator); } public void setScopeMetadataResolver (ScopeMetadataResolver scopeMetadataResolver) { this .reader.setScopeMetadataResolver(scopeMetadataResolver); this .scanner.setScopeMetadataResolver(scopeMetadataResolver); } public void register (Class<?>... annotatedClasses) { Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified" ); this .reader.register(annotatedClasses); } public void scan (String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified" ); this .scanner.scan(basePackages); } public <T> void registerBean (Class<T> annotatedClass, Object... constructorArguments) { registerBean(null , annotatedClass, constructorArguments); } public <T> void registerBean (@Nullable String beanName, Class<T> annotatedClass, Object... constructorArguments) { this .reader.doRegisterBean(annotatedClass, null , beanName, null , bd -> { for (Object arg : constructorArguments) { bd.getConstructorArgumentValues().addGenericArgumentValue(arg); } }); } @Override public <T> void registerBean (@Nullable String beanName, Class<T> beanClass, @Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) { this .reader.doRegisterBean(beanClass, supplier, beanName, null , customizers); } }
通过上面的源码分析,我们可以看到Spring对注解的处理分为两种方式:
直接将注解Bean注册到容器中。可以在初始化容器时注册,也可以在容器创建之后手动调用注册方法向容器注册,然后通过手动刷新容器,使得容器对注册的注解Bean进行处理
通过扫描指定的包及其子包下的所有类。在初始化注解容器时指定要自动扫描的路径,如果容器创建以后向给定路径动态添加注解Bean,则需要手动调用容器扫描方法,然后手动刷新容器,使得容器对锁注册的Bean进行处理
接下来,将会对两种处理方式详细分析其实现过程
读取Annotation元数据 直接将注解Bean注册到容器中 AnnotationConfigApplicationContext
通过调用注解Bean定义读取器
AnnotatedBeanDefinitionReader
的 register()
方法向容器注册指定注解Bean,注解Bean定义读取器向容器注册注解Bean的源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 public void register (Class<?>... annotatedClasses) { for (Class<?> annotatedClass : annotatedClasses) { registerBean(annotatedClass); } }public void registerBean (Class<?> annotatedClass) { doRegisterBean(annotatedClass, null , null , null ); }public <T> void registerBean (Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier) { doRegisterBean(annotatedClass, instanceSupplier, null , null ); }public <T> void registerBean (Class<T> annotatedClass, String name, @Nullable Supplier<T> instanceSupplier) { doRegisterBean(annotatedClass, instanceSupplier, name, null ); }@SuppressWarnings("unchecked") public void registerBean (Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) { doRegisterBean(annotatedClass, null , null , qualifiers); }@SuppressWarnings("unchecked") public void registerBean (Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) { doRegisterBean(annotatedClass, null , name, qualifiers); } <T> void doRegisterBean (Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition (annotatedClass); if (this .conditionEvaluator.shouldSkip(abd.getMetadata())) { return ; } abd.setInstanceSupplier(instanceSupplier); ScopeMetadata scopeMetadata = this .scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this .beanNameGenerator.generateBeanName(abd, this .registry)); AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); if (qualifiers != null ) { for (Class<? extends Annotation > qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true ); } else if (Lazy.class == qualifier) { abd.setLazyInit(true ); } else { abd.addQualifier(new AutowireCandidateQualifier (qualifier)); } } } for (BeanDefinitionCustomizer customizer : definitionCustomizers) { customizer.customize(abd); } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder (abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this .registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this .registry); }
通过上面的源码分析,我们可以看到注册注解Bean定义类的基本步骤:
需要使用注解元数据解析器计息注解Bean中关于作用域的配置。
使用AnnotationConfigUtils
的processCommonDefinitionAnnotations
()方法处理注解Bean定义类中通用注解。
使用AnnotationConfigUtils
的appliyScopedProxyMode()
方法创建对于作用域的代理对象。
通过BeanDefinitaionReaderUtils
向容器注册Bean。
AnnotationScopeMetadataResolver
解析作用域元数据
AnnotationScopeMetadataResolver
通过 resolveScopeMetadata()
方法解析注册Bean定义类的作用域元信息,即判断注册的Bean是原型类型(prototype )还是单例类型(singleton ),其源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Override public ScopeMetadata resolveScopeMetadata (BeanDefinition definition) { ScopeMetadata metadata = new ScopeMetadata (); if (definition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this .scopeAnnotationType); if (attributes != null ) { metadata.setScopeName(attributes.getString("value" )); ScopedProxyMode proxyMode = attributes.getEnum("proxyMode" ); if (proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = this .defaultProxyMode; } metadata.setScopedProxyMode(proxyMode); } } return metadata; }
上述代码中:AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this.scopeAnnotationType);
这里就是获取对象中指定类型的注解值。
AnnotationConfigUtils
处理注解Bean定义类中的通用注解
AnnotationConfigUtils
类的 processCommonDefinitionAnnotations()
在向容器注册Bean之前,首先对注解Bean定义类中的通用Spring注解进行处理,源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public static void processCommonDefinitionAnnotations (AnnotatedBeanDefinition abd) { processCommonDefinitionAnnotations(abd, abd.getMetadata()); }static void processCommonDefinitionAnnotations (AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); if (lazy != null ) { abd.setLazyInit(lazy.getBoolean("value" )); } else if (abd.getMetadata() != metadata) { lazy = attributesFor(abd.getMetadata(), Lazy.class); if (lazy != null ) { abd.setLazyInit(lazy.getBoolean("value" )); } } if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true ); } AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null ) { abd.setDependsOn(dependsOn.getStringArray("value" )); } if (abd instanceof AbstractBeanDefinition) { AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd; AnnotationAttributes role = attributesFor(metadata, Role.class); if (role != null ) { absBd.setRole(role.getNumber("value" ).intValue()); } AnnotationAttributes description = attributesFor(metadata, Description.class); if (description != null ) { absBd.setDescription(description.getString("value" )); } } }
AnnotationConfigUtils
根据注解Bean定义类中配置的作用域为其应用响应的代理策略
AnnotationConfigUtils
类的 applyScopedProxyMode()
方法根据注解Bean定义类中配置的作用域@Scope
注解的值,为Bean定义应用响应的代理模式,主要是在Spring面向切面编程(AOP)中使用。
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 static BeanDefinitionHolder applyScopedProxyMode ( ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); if (scopedProxyMode.equals(ScopedProxyMode.NO)) { return definition; } boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); }
这段为Bean引用创建相应模式的代理。这里不做深入分析。
BeanDefinitionReaderUtils
向容器注册Bean
BeanDefinitionReaderUtils主要是校验BeanDefinition信息,然后将Bean添加到容器中一个管理BeanDefinition的HashMap中。
扫描指定包并解析为BeanDefinition 当创建注解处理器时,如果传入的初始参数是注解Bean定义类锁在的包时,注解容器将扫描给定的包及其子包,将扫描到的注解Bean定义载入并注册。
ClassPathBeanDefinitionScanner
扫描给定的包及其子包
AnnotationConfigApplicationContext通过调用类路径Bean定义扫描ClassPathBeanDefinitionScanner扫描给定包及其子包下的所有类,主要源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider { private final BeanDefinitionRegistry registry; private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults (); @Nullable private String[] autowireCandidatePatterns; private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator (); private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver (); private boolean includeAnnotationConfig = true ; public ClassPathBeanDefinitionScanner (BeanDefinitionRegistry registry) { this (registry, true ); } public ClassPathBeanDefinitionScanner (BeanDefinitionRegistry registry, boolean useDefaultFilters) { this (registry, useDefaultFilters, getOrCreateEnvironment(registry)); } public ClassPathBeanDefinitionScanner (BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) { this (registry, useDefaultFilters, environment, (registry instanceof ResourceLoader ? (ResourceLoader) registry : null )); } public ClassPathBeanDefinitionScanner (BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null" ); this .registry = registry; if (useDefaultFilters) { registerDefaultFilters(); } setEnvironment(environment); setResourceLoader(resourceLoader); } @Override public final BeanDefinitionRegistry getRegistry () { return this .registry; } public void setBeanDefinitionDefaults (@Nullable BeanDefinitionDefaults beanDefinitionDefaults) { this .beanDefinitionDefaults = (beanDefinitionDefaults != null ? beanDefinitionDefaults : new BeanDefinitionDefaults ()); } public BeanDefinitionDefaults getBeanDefinitionDefaults () { return this .beanDefinitionDefaults; } public void setAutowireCandidatePatterns (@Nullable String... autowireCandidatePatterns) { this .autowireCandidatePatterns = autowireCandidatePatterns; } public void setBeanNameGenerator (@Nullable BeanNameGenerator beanNameGenerator) { this .beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator ()); } public void setScopeMetadataResolver (@Nullable ScopeMetadataResolver scopeMetadataResolver) { this .scopeMetadataResolver = (scopeMetadataResolver != null ? scopeMetadataResolver : new AnnotationScopeMetadataResolver ()); } public void setScopedProxyMode (ScopedProxyMode scopedProxyMode) { this .scopeMetadataResolver = new AnnotationScopeMetadataResolver (scopedProxyMode); } public void setIncludeAnnotationConfig (boolean includeAnnotationConfig) { this .includeAnnotationConfig = includeAnnotationConfig; } public int scan (String... basePackages) { int beanCountAtScanStart = this .registry.getBeanDefinitionCount(); doScan(basePackages); if (this .includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this .registry); } return (this .registry.getBeanDefinitionCount() - beanCountAtScanStart); } protected Set<BeanDefinitionHolder> doScan (String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified" ); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet <>(); for (String basePackage : basePackages) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this .scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this .beanNameGenerator.generateBeanName(candidate, this .registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder (candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this .registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this .registry); } } } return beanDefinitions; } ... }
类路径Bean定义扫描器ClassPathBeanDefinitionScanner
主要通过findCandidateComponents
()方法调用其父类ClassPathScanningCandidateComponentProvider
类来扫描获取给定包及其子包下的类。
ClassPathScanningCandidateComponentProvider
扫描给定包及其子包的类
ClassPathScanningCandidateComponentProvider
类的 findCandidateComponents()
方法具体实现扫描给定类路径包的功能,主要源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable , ResourceLoaderAware { static final String DEFAULT_RESOURCE_PATTERN = "**/*.class" ; protected final Log logger = LogFactory.getLog(getClass()); private String resourcePattern = DEFAULT_RESOURCE_PATTERN; private final List<TypeFilter> includeFilters = new LinkedList <>(); private final List<TypeFilter> excludeFilters = new LinkedList <>(); ... public ClassPathScanningCandidateComponentProvider (boolean useDefaultFilters) { this (useDefaultFilters, new StandardEnvironment ()); } public ClassPathScanningCandidateComponentProvider (boolean useDefaultFilters, Environment environment) { if (useDefaultFilters) { registerDefaultFilters(); } setEnvironment(environment); setResourceLoader(null ); } ..... @SuppressWarnings("unchecked") protected void registerDefaultFilters () { this .includeFilters.add(new AnnotationTypeFilter (Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this .includeFilters.add(new AnnotationTypeFilter ( ((Class<? extends Annotation >) ClassUtils.forName("javax.annotation.ManagedBean" , cl)), false )); logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning" ); } catch (ClassNotFoundException ex) { } try { this .includeFilters.add(new AnnotationTypeFilter ( ((Class<? extends Annotation >) ClassUtils.forName("javax.inject.Named" , cl)), false )); logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning" ); } catch (ClassNotFoundException ex) { } } ....... public Set<BeanDefinition> findCandidateComponents (String basePackage) { if (this .componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this .componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); } } ....... private Set<BeanDefinition> addCandidateComponentsFromIndex (CandidateComponentsIndex index, String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet <>(); try { Set<String> types = new HashSet <>(); for (TypeFilter filter : this .includeFilters) { String stereotype = extractStereotype(filter); if (stereotype == null ) { throw new IllegalArgumentException ("Failed to extract stereotype from " + filter); } types.addAll(index.getCandidateTypes(basePackage, stereotype)); } boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (String type : types) { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type); if (isCandidateComponent(metadataReader)) { AnnotatedGenericBeanDefinition sbd = new AnnotatedGenericBeanDefinition ( metadataReader.getAnnotationMetadata()); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Using candidate component class from index: " + type); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + type); } } } else { if (traceEnabled) { logger.trace("Ignored because matching an exclude filter: " + type); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException ("I/O failure during classpath scanning" , ex); } return candidates; } private Set<BeanDefinition> scanCandidateComponents (String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet <>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this .resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition (metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException ( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException ("I/O failure during classpath scanning" , ex); } return candidates; } ....... protected boolean isCandidateComponent (MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this .excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false ; } } for (TypeFilter tf : this .includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false ; } ....... }
注册注解BeanDefinition
AnnotationConfigWebApplicationContext
是 AnnotationConfigApplicationContext
的 Web 版, 它们对于注解 Bean 的注册和扫描是基本相同的,但是 AnnotationConfigWebApplicationContext
对注解 Bean 定义的载入稍有不同,AnnotationConfigWebApplicationContext
注入注解 Bean 定义 源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 @Override protected void loadBeanDefinitions (DefaultListableBeanFactory beanFactory) { AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory); ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory); BeanNameGenerator beanNameGenerator = getBeanNameGenerator(); if (beanNameGenerator != null ) { reader.setBeanNameGenerator(beanNameGenerator); scanner.setBeanNameGenerator(beanNameGenerator); beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator); } ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver(); if (scopeMetadataResolver != null ) { reader.setScopeMetadataResolver(scopeMetadataResolver); scanner.setScopeMetadataResolver(scopeMetadataResolver); } if (!this .annotatedClasses.isEmpty()) { if (logger.isInfoEnabled()) { logger.info("Registering annotated classes: [" + StringUtils.collectionToCommaDelimitedString(this .annotatedClasses) + "]" ); } reader.register(this .annotatedClasses.toArray(new Class <?>[this .annotatedClasses.size()])); } if (!this .basePackages.isEmpty()) { if (logger.isInfoEnabled()) { logger.info("Scanning base packages: [" + StringUtils.collectionToCommaDelimitedString(this .basePackages) + "]" ); } scanner.scan(this .basePackages.toArray(new String [this .basePackages.size()])); } String[] configLocations = getConfigLocations(); if (configLocations != null ) { for (String configLocation : configLocations) { try { Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader()); if (logger.isInfoEnabled()) { logger.info("Successfully resolved class for [" + configLocation + "]" ); } reader.register(clazz); } catch (ClassNotFoundException ex) { if (logger.isDebugEnabled()) { logger.debug("Could not load class for config location [" + configLocation + "] - trying package scan. " + ex); } int count = scanner.scan(configLocation); if (logger.isInfoEnabled()) { if (count == 0 ) { logger.info("No annotated classes found for specified class/package [" + configLocation + "]" ); } else { logger.info("Found " + count + " annotated classes in package [" + configLocation + "]" ); } } } } } }
以上就是解析和注入注解配置资源的全过程分析
参考:https://github.com/wenbin8/doc/blob/master/Spring/02-Spring-IOC%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.md
IOC容器总结 现在通过上面的代码,总结一下IOC容器初始化的基本步骤:
初始化的入口在容器实现中的refresh()
调用来完成。
对Bean定义载入IOC容器使用的方法是loadBeanDefinition()
,其中大致过程如下:通过ResourceLoader
来完成资源文件位置的定位,DefaultResourceLoader
是默认实现,同时上下文本身就给出了ResourceLoader
的实现,可以从类路径、文件系统、URL等方式来定位资源位置。如果是XmlBeanFactory
作为IOC容器,那么需要为它指定Bean定义的资源,也就是Bean定义文件时通过Resource来把IOC容器处理,容器通过BeanDefinitionReader
来完成定义信息的解析和Bean信息注册,往往使用的是XmlBeanDefinitionReader
来解析Bean的XML定义文件,实际处理过程是委托给BeanDefinitionParserDelegate
来完成的,从而得到bean的定义信息,这些信息在Spring中使用BeanDefinition对象来表示,这个名字可以让我们想到 loadBeanDefinition()
,registerBeanDefinition()
这些相关方法。它们都是为处理 BeanDefinitin 服务的,容器解析得到 BeanDefinition 以后,需要把它在 IOC 容器中注册,这由IOC实现BeanDefinitionRegistry
接口来实现。注册过程就是在IOC容器内部维护的一个 HashMap来保存得到的BeanDefinition的过程。这个HashMap是IOC容器持有Bean信息的场所,以后对Bean的操作都是围绕这个HashMap来实现的。
然后通过BeanFactory
和ApplicationContext
来享受到Spring IOC的服务了,在使用IOC容器的时候,我们注意到除了少量粘合代码,绝大多数以正确 IOC 风格编写的应用程序代码完全不用关心如何到达工厂,因为容器将把这些对象与容器管理的其他对象钩在一起。基本的策略是把工厂放到已知的地方,最好是放在对预期使用的上下文有意义的地方,以及代码将实际需要访问工厂的地方。Spring 本身提供了对声明式载入 web 应用程序用法的应用程序上下文,并将其存储在 ServletContext
中的框架 实现