spring启动简析
spring类结构
beanFactory结构
todo
applicationContext结构
todo
beanDefinition结构
BeanDefinition是顶层接口,定义了bean的各种属性,包括是否懒加载,类名称等等,所有bean的基本属性都是应该通过这个接口获取。BeanDefinition直接继承的是接口AnnotatedBeanDefinition与AbstractBeanDefinition抽象类,AnnotatedBeanDefinition是在BeanDefinition基础上增加了AnnotationMetadata属性数据,这个接口可以理解为带注解的BeanDefinition;AbstractBeanDefinition是对BeanDefinition的基本实现,把BeanDefinition中大部分方法都实现了,然后这个抽象类有三个子类RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition,对于前面两个父子类,是因为我们定义bean的时候,是可以有parent关系的,RootBeanDefinition是一种merged过的BeanDefinition,是完整的BeanDefinition,而childBeanDefinition是不完整的BeanDefinition,必须要包含parent的BeanDefinition;GenericBeanDefinition是新的BeanDefinition,是用来替换那个root跟child的,后面新的beandefinition都是基于GenericBeanDefinition实现的。再来看下AnnotatedBeanDefinition的子类有两个ScannedGenericBeanDefinition跟AnnotatedGenericBeanDefinition,这两个子类都是基于GenericBeanDefinition实现的,看下这两个类的实现是差不多的,这两个类的区别在与ScannedGenericBeanDefinition是在component-scan的场景下定义的,就是我们注解@ComponentScan或者<context: component-scan>而AnnotatedGenericBeanDefinition应用的场景是springboot的AnnotationConfigApplicationContext里面以及处理@Configuration注解的bean对象的时候用的。而普通的GenericBeanDefinition注解在xml中定义的bean应用
metadata结构
todo
namespaceHandler结构
todo
spring中的数据结构
todo
spring 的初始化----refresh
spring启动过程是以ApplicationContext对象的定义来完成bean的初始化与管理的。然后就可以通过这个context的getbean方法获取对应bean对象。以ClassPathXmlApplicationContext为例,当我们new一个ClassPathXmlApplicationContext对象的时候,其spring的bean对象已经被加载好了。
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
上面代码中是ClassPathXmlApplicationContext的构造函数,configLocations是用户指定的配置项路径地址,不是重点,重点在refresh函数
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
prepareRefresh()方法做准备工作,实现中没有做什么事。
bean的加载----obtainFreshBeanFactory
obtainFreshBeanFactory是核心方法步骤,这个方法主要就是构建beanFactory以及加载所有需要定义成bean的对象,创建对应的beanDefinition。跟踪obtainFreshBeanFactory的方法,发现springcontext中定义的beanfactory是DefaultListableBeanFactory,这个是spring提供的一个默认的bean工厂实现类。
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
customizeBeanFactory是对这个beanfactory的定制,这里定制了两个属性,一个是allowBeanDefinitionOverriding,就是是否允许bean覆盖定义,默认是允许的,当有两个相同名字的bean定义时,后者会覆盖前者;另一个是allowCircularReferences,就是是否允许bean的循环引用,默认是允许的,后面会讲spring是如何解决bean的循环引用的。默认的DefaultListableBeanFactory这两个配置项是true,不需要修改。
loadBeanDefinitions方法是核心方法,这个方法就是把spring里面所有需要其管理的bean对象给加载起来(只是定义,没有初始化)
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
这个XmlBeanDefinitionReader是xml文件的bean解析器,代码到这里,beanfactory的bean的定义模型beanDefinition的读取实际是交给beanDefinitionReader这个对象来做的,因为我们开始选择的是ClassPathXmlApplicationContext,所以这里加载beandefinition是加载的xml形式定义的,所以实际上所有的xml中定义的bean的读取的就是这个对象XmlBeanDefinitionReader完成的。上面的核心代码在于loadBeanDefinitions(beanDefinitionReader)这个方法,这个方法里面就把applicationContext的loadBeanDefinition动作交给了XmlBeanDefinitionReader去完成,实际上就是XmlBeanDefinitionReader进行loadBeanDefinitions
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
这个方法里面是加载bean对象,getConfigResources获取资源配置,这个资源配置就是我们在定义ClassPathXmlApplicationContext对象的时候传入的,如果为空,则加载默认的配置文件/WEB-INF/applicationContext.xml(用的云服务nuwa容器启动时候,会将相关的配置资源加载进去),跟踪这个loadBeanDefinitions方法可以看到,reader是遍历加载configLocations,由于applicationcontext继承ResourcePatternResolver,说明applicationcontext的resourceLoader是通配符匹配resource路径,然后把每个resourcelocation下正则匹配的resource文件进行解析,继续跟踪代码走到doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
...
}
doLoadBeanDefinitions里面有两行有效代码,一个doLoadDocument就是从resource资源文件读取出来,加载到Document对象中,这里主要是DOM的解析,不做分析,另外一个registerBeanDefinitions就是真正将doc中定义的bean解析成beanDefinition对象,注册到beanfactory中。
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
这里BeanDefinitionDocumentReader 对象是用来读取一个doc文件中的beandefinition的,每一个resource都被封装成一个xmlreaderContext (注意这个xmlreaderContext 里面会指定一个NamespaceHandlerResolver,这个resolver是用来解析我们配置的xml的)。调用的方法registerBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
但是这里用了一个BeanDefinitionParserDelegate,这个delegate是readerContext的代理,这个方法中,核心代码是parseBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
解析过程是从root开始的,每个元素进行解析,根据元素的命名空间区分是自带的还是用户自定义的,先看下系统自带的元素
public static final String ALIAS_ATTRIBUTE = "alias";
public static final String IMPORT_ELEMENT = "import";
public static final String RESOURCE_ATTRIBUTE = "resource";
public static final String NESTED_BEANS_ELEMENT = "beans";
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
可以看出这里就是解析几种常见的配置bean的元素,注意在处理beans的时候,是用递归的方式处理bean的加载。下面看下custom的方式,在配置xml中有很多是自定义的,比如,等等,这里讲下这些自定义格式的bean的加载与解析。
自定义标签----元素解析
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
首先获取元素的命名空间,根据命名空间获取对应的解析器,然后用解析器去执行元素的解析工作,这里看下handler对象是从readerContext中获取的,分析下这个handler代码,getNamespaceHandlerResolver获取命名空间对应的处理器的解析器,spring中提供了一个默认的解析器DefaultNamespaceHandlerResolver,维护namespace跟handler的解析关系,核心点在于维护一个map,key就是namespace,value就是对应的handler
public NamespaceHandler resolve(String namespaceUri) {
Map<String, Object> handlerMappings = getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "] not found", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "]: problem with handler class file or dependent class", err);
}
}
}
上面的代码逻辑比较简单,就是从一个map中获取这个namespace对应的handler,这个handler对象可以是handler实例本身,也可以是类名称,如果是类名称的话,就类加载器加载,NamespaceHandler是一个接口,spring提供了一个适配器类NamespaceHandlerSupport,实现了NamespaceHandler接口的通用方法,把配置解析绑定到BeanDefinitionParser上,一个配置对应一个BeanDefinitionParser,维护到一个map里面,那么NamespaceHandler的parse接口,就是获取对应parser来处理。
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext).parse(element, parserContext);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
String localName = parserContext.getDelegate().getLocalName(element);
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
所以我们可以看到一个NamespaceHandler对应的是一种namespace处理器,一般也是一个xml里面,比如我们说的对应的就一个DubboNamespaceHandler,而一个xml里面可以有多种配置前缀,比如里面有、等,里面每一个小的配置类型对应的是一个parser,这个parser做的事情就是把对应的配置定义转换成beanDefinition,注册到beanfactory中(这个beanfactory在对应的readerContext里面)所以我们看下dubbo的DubboNamespaceHandler的类的定义
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
@Override
public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
}
在init方法地方把每个配置类型以及对应的parser注册到namespaceHandler里面,然后这个DubboNamespaceHandler又通过SPI方式注册到NamespaceHandlerResolver里面,我们看下前面提到的DefaultNamespaceHandlerResolver里面如何加载这些定义的namespaceHandler的。
private Map<String, Object> getHandlerMappings() {
if (this.handlerMappings == null) {
synchronized (this) {
if (this.handlerMappings == null) {
try {
Properties mappings =
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isDebugEnabled()) {
logger.debug("Loaded NamespaceHandler mappings: " + mappings);
}
Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
}
catch (IOException ex) {
throw new IllegalStateException(
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
}
}
}
}
return this.handlerMappings;
}
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
里面的PropertiesLoaderUtils.loadAllProperties就是用来加载namespaceHandler,这里的this.handlerMappingsLocation 最终初始化的是META-INF/spring.handlers。至于自定义的parser如何解析这里就不分析了。
里面的PropertiesLoaderUtils.loadAllProperties就是用来加载namespaceHandler,这里的this.handlerMappingsLocation 最终初始化的是META-INF/spring.handlers。至于自定义的parser如何解析这里就不分析了。
小结
spring对bean的解析(xml)有两种,原生定义了几种标签,比如、、等,这些spring提供默认的处理,还可以支持拓展的,spring中也拓展了很多bean格式,比如context标签,dubbo也拓展了,拓展bean的标签的目的是用户自定义bean的创建方式。对应的步骤如下:
- 首先要定义dtd文件,定义自己要用的标签元素、属性以及对应的子元素等等
- 自定义NamespaceHandler子类,可以继承NamespaceHandlerSupport,然后对于每个子配置类型,需要自定义对应的BeanDefinitionParser,每个parser就是对我们自定义标签的解析。
- 然后在对应的NamespaceHandler类里面进行注册----在init方法中调用registerBeanDefinitionParser方法,把每个parser注册进去。
- 在META-INF/spring.handlers文件里面按照SPI配置自定义的NamespaceHandler由DefaultNamespaceHandlerResolver加载。
自定义配置案例分析----componant-scan、annotation-config配置解析
component-scan配置就是自定义配置的一种,就是xml配置中配置,他的作用是用来扫描包路径下所有的类文件,对表明@Component注解的类加载成bean对象。对应的NamespaceHandler是ContextNamespaceHandler,举例一个配置
<context:component-scan base-package="com.vrv.paw.dao,com.vrv.paw.service,com.vrv.paw.action" />
代码如下
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}
看到component-scan子配置对应的解析类为ComponentScanBeanDefinitionParser,查看对应的parse实现
public BeanDefinition parse(Element element, ParserContext parserContext) {
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
BASE_PACKAGE_ATTRIBUTE对应的配置项就是 base-package,解析获取对应的package列表,创建ClassPathBeanDefinitionScanner对象scanner,来扫描这些base-packages下的bean注解定义,然后把扫描出来的beanDefinitions注册到beanfactory中,这里的核心方法就是doScan。注意下在doScan之前的方法configureScanner,这个就是为了获取一个scanner,后面会讲到这个方法。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
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;
}
这个方法就是遍历所有的basePackage,把对应package下的bean都加载起来,扫描的方法是findCandidateComponents,进入这个方法(筛选主要部分)
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = this.resourcePatternResolver.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 = this.metadataReaderFactory.getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
...
return candidates;
}
从上面代码可以看出先用resourcePatternResolver获取这个basePackage下的class文件,加载成resource,这个resourcePatternResolver对应的类是PathMatchingResourcePatternResolver,就是类路径资源解析器,不进入分析。下面是对每个resource获取对应的MetadataReader,这个MetadataReader对象是用来获取class类文件的元数据的,包括注解、Class类元数据等。然后isCandidateComponent方法就是判断这个类是否有注解
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return isConditionMatch(metadataReader);
}
}
return false;
}
这里就是把metadata数据判断是否满足过滤器,也就是我们配置在<context: component-scan/>的子元素<context: include-filter/>中,这个子元素的配置是可以让我们自定义bean注解(比如这里我们配置com.huawei.chj.ChjAnnotation,那么@ChjAnnotation注解的类就会被扫描成bean),一般的我们不会去配置这个值,而是用默认的配置,对应的是属性use-default-filters=true,默认就是true,所以这里的includeFilters就是默认的filter,可以看下对应的定义,就是在前面我们调用configureScanner方法里面,我们回过来看下这个方法实现
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
boolean useDefaultFilters = true;
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
}
// Delegate bean definition registration to scanner class.
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
}
try {
parseBeanNameGenerator(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
try {
parseScope(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
parseTypeFilters(element, scanner, parserContext);
return scanner;
}
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
readerContext.getEnvironment(), readerContext.getResourceLoader());
}
在这个方法里面就会调用createScanner方法创建scanner(其他的先不关注),里面就是new一个ClassPathBeanDefinitionScanner,看下这个类的构造函数:
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
到这里可以看到会调用registerDefaultFilters来初始化默认的filter,进入这个方法看下
javaprotected 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) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
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) {
// JSR-330 API not available - simply skip.
}
}
到这里我们就看到了这个filters里面把Component注解类加到filter中去了,这就是我们在类上配置@Component注解就会被扫描成bean的原因,当然这里不仅仅添加了Component,还有javax.annotation.ManagedBean跟javax.inject.Named,所以实际上我们在类上配置@ManagedBean跟@Named都是可以被扫描成bean的。
回到前面讲的findCandidateComponents方法,通过这个方法把所有的basePackage里面的类中注解@Component的加载成beandefinition,这些都是“候选”bean对象,接下来要对这些对象进行处理,主要方法是AnnotationConfigUtils.processCommonDefinitionAnnotations,进入这个方法分析下:
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"));
}
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
这里所说对common属性就是定义bean对属性,包括是否懒加载,是否有依赖的类,是否有描述的注解等等。这些在xml配置中是不要处理的,会在解析xml对时候就处理了。
到此doscan已经完成,此时所有对注解对bean都被扫描到了,但是还没有初始化,接下来的方法registerComponents很重要,网上资料说标签有了就不需要,包含进去了,具体实现就在这个方法中:
protected void registerComponents(
XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
Object source = readerContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
}
// Register annotation config processors, if necessary.
boolean annotationConfig = true;
if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
}
if (annotationConfig) {
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
}
}
readerContext.fireComponentRegistered(compositeDef);
}
前面的compositeDef先不用管,直接看到annotationConfig,默认这个配置是true,那么就会执行AnnotationConfigUtils.registerAnnotationConfigProcessors,这个方法比较长,但是做对事情比较简单,就是把ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor(JSR-250)等processor加进来,这几个类ConfigurationClassPostProcessor-----处理@Configuration注解;AutowiredAnnotationBeanPostProcessor-----处理Autowired、value、inject注解;CommonAnnotationBeanPostProcessor----处理JSR-250标准对注解,比如说我们用的@Resource注解。这个注解对应对parser类就不再分析类,核心功能就是上面这个方法。
小结
回顾整个component-scan的流程,首先是我们在解析xml中,发现了有自定义的标签了,然后从用resolver解析器找到这个标签对应的namespaceHandler,这个namespaceHandler是保存在map中,初始化是通过SPI方式加载进来的(namespace-handler配置)。找到这个namespaceHandler后,解析标签,找到ComponentScanBeanDefinitionParser解析类,这个类就会根据component-scan中配置的basePackage来扫描对应的class类,把有注解@Component的类作为候选bean,处理下这些类上的其他的类注解:比如是否懒加载、是否有依赖、是否有描述等等。处理好了后就把这些beandefinition注册到beanfactory中,最后再添加@Configuration、@Autowire 的注解处理器。这样这个scan流程就完成了。
所以可以知道xml中定义的bean跟@Component注解的bean在构建beanfactory的时候就已经加载到beanfactory中,但是@Configuration注解的类以及类里面@Bean注解的方法此时还没有加载,以及每个bean中的IOC都没有做,这些事情是在后面调用
小结
到这里此时完成了方法obtainFreshBeanFactory(),仅仅把所有的xml中定义的bean以及@Component注解的bean都已经加载到beanfatcory中了,流程比较清晰,先创建一个默认的beanfactory,然后把指定location的resource给加载解析,从xml中分析出bean对象来,注册到beanfactory中,这里的beandefinition是无差别的,不管是普通的bean,还是factorybean,还是各种processor。
beanfactory后置处理----invokeBeanFactoryPostProcessors
此时的bean还是一个beanDefinition对象,没有初始化,只是做了构造创建。接下来prepareBeanFactory、postProcessBeanFactory做了初步配置,暂时不做分析,下面是invokeBeanFactoryPostProcessors方法,这个是spring的非常核心的一个方法调用,很多的业务定制都在这里完成的,比如说我们的@Configuration。这个方法是调用所有beanfactoryPostProcessor,执行对应的postProcessBeanFactory方法。
spring提供了beanfactoryPostProcessor接口,这个是spring在加载beandefinition后,初始化bean前,做的操作,用来给给我们对beanfactory中的beandefinition做一些定制。另外还有一个BeanDefinitionRegistryPostProcessor接口,这个接口用来给业务做自定义的beandefinition的注册
这个里面主要是用到对应的代理方法:PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors,这个方法很长,逐步来分析
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
。。。
这个方法很长,干的事情很清晰,就是把spring容器中BeanFactoryPostProcessor类型的bean单独拿出来处理这个流程整理如下:
- 从beanfactory中取出类型BeanDefinitionRegistryPostProcessor的beandefinistion列表
- 过滤出实现接口PriorityOrdered的Processors,然后排序
- 执行这些BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
- 重新从beanfactory中取出类型BeanDefinitionRegistryPostProcessor的beandefinistion列表
- 过滤出实现接口Ordered的Processors,然后排序
- 执行这些BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
- 重新从beanfactory中取出类型BeanDefinitionRegistryPostProcessor的beandefinistion列表
- 执行这些BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
- 执行上面这些BeanDefinitionRegistryPostProcessors的postProcessBeanFactory方法
- 从beanfactory中取出类型BeanFactoryPostProcessor的beandefinistion列表
- 按照上面的顺序从PriorityOrdered、Ordered、普通的三种顺序来执行对应的postProcessBeanFactory
说明1:对于步骤4跟步骤7,需要重新从beanfactory中获取beandefinistion列表是因为前面每一次操作都可能会创建新的BeanDefinitionRegistryPostProcessor的beandefinition,所以需要重新获取
说明2:每次处理低优先级的processor时,都会去检查已处理列表,避免被多次执行。
这样整理下流程就比较清晰。前面在处理自定义标签的时候,在对应的namespaceHandler里面,doScan的时候,我们注册了三个processor,其中有一个是ConfigurationClassPostProcessor,这个是处理@Configuration的,以这个为例分析下BeanDefinitionRegistryPostProcessor的具体处理过程
BeanDefinitionRegistryPostProcessor处理分析----ConfigurationClassPostProcessor
ConfigurationClassPostProcessor是用来处理@Configurtaion的,看下对应的处理方法
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
// 1、从所有的候选的bean中,筛选出@Configuration注解的bean
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 解析bean
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// Can reuse the pre-parsed metadata from the given BeanDefinition...
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// Check already loaded Class if present...
// since we possibly can't even load the class file for this Class.
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
BeanPostProcessor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {
return false;
}
metadata = AnnotationMetadata.introspect(beanClass);
}
else {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " +
className, ex);
}
return false;
}
}
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
- 首先是从所有的beandefinition中获取@configuration注解的bean,主要是方法ConfigurationClassUtils.checkConfigurationClassCandidate,这个检查动作主要就是获取bean的注解是否是@configuration,是就作为注解类
- 将待处理的bean进行处理,处理流程主要是在doProcessConfigurationClass方法中完成, 在@Configurtaion中主要处理的事情:
- 处理内部类的注解(包含component,import,configuration、@bean等等),这个是一个递归处理
- 处理@PropertySource 注解
- 处理@Component-scan注解
- 处理@import @importSource注解
- 处理@Bean注解,注意这里处理bean注解不是直接解析bean,而是把方法加入到beanMethod中,待后面处理
注意下,这里说的各种注解必须是在@Configuration注解下的,否则不会被处理,这是因为这些注解的处理都是在处理@Configuration中处理的。@PropertySource 是导入配置文件,configruationPlaceHolder就是处理各种PropertySource对象,@Import处理导入的对象为bean,@ImportSource处理导入的xml配置
这里有processMemberClasses的方法,可以看下源码,因为是递归调用。所以当我们内部类之间是循环导入的就会出现死循环,报错,一般很少出现这样的问题,而且有个问题待验证:我们在component-scan的时候,会把类以及内部类都扫描到,如果有注解才会成bean,那么对于一个普通的含有内部类的bean,这里的内部类是否不需要再处理了?因为已经被scan了,只有是启动springcontext的那个启动类本身才需要处理内部类?这个待验证
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
bean的初始化–finishBeanFactoryInitialization
经过前面的beanfactorypostprocessor之后,当前spring容器的所有的bean都被加载到容器中,下面就需要进行实例化与初始化了,这部分的代码会比较长。
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
上面的流程比较清楚,总结流程如下:
- 获取加载的beandefinition列表,获取merged过后的beandefinition对象,getMergedLocalBeanDefinition方法下面重点分析
- 过滤出非抽象的,单例的,非懒加载的beandefinition进行初始化
- 判断是否是factorybean,如果是,按照factorybean的方式处理,如果是普通的bean,则调用getbean方式来初始化
- 过滤出实现SmartInitializingSingleton的bean,做一些初始化后的后置处理
这里面 有两个核心方法:getMergedLocalBeanDefinition,getBean
bean的整理–getMergedLocalBeanDefinition
前面加载的beandefinition仅仅是定义了bean以及做了简单的配置,有些bean需要合并些配置,比如说父子bean对象,需要合并后才是一个完整的beandefinition
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
这个方法主要是处理那些不是完整的bean的,因为spring支持bean的继承(类似我们把公共部分提取到parent中),parent不支持实例化,子bean不能直接实例化,所以才有这个方法的,看下方法的逻辑
- 从spring容器beandefinitionMap中根据这个beanName获取beandefinition。
- 检查这个beandefinition是否有parentdefinition,如果没有,则说明这个bean就是一个完整的beandefinition,直接将其转换成RootBeanDefinition。
- 如果这个bean有parentdefinition,则递归去获取parentbeandefinition,然后将子beandefinition 与其合并,调用overrideFrom方法完成。
到此,所有的bean都是完整的了。
bean初始化与获取----getBean
spring容器中,不管是factorybean还是普通的bean,都是通过方法getBean来进行初始化的。这个方法非常长,可以分段分析
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
首先是transformedBeanName,这个是获取bean的Name,在spring中,对于factorybean,beanname是有前缀&的,这个方法就是把这个&给过滤掉。然后getSingleton方法从map中获取这个bean,因为我们此时初始化bean是单例的,非单例不在这里初始化,获取的时候优先从这个map中获取,没有才考虑去创建。如果map中有的话,直接去取,但是bean有两种,一种是factorybean,一种是普通bean,两种bean的获取方式是不一样的,进入这个方法看下具体的实现getObjectForBeanInstance
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
- 这个方法,首先是用BeanFactoryUtils.isFactoryDereference(name)判断是否是factorybean,如果是以&开头,则必须是factorybean(但是这里注意下并不是所有的factorybean的name都是以&开头,对于不去显示配置beanname的bean,spring会给他分配一个beanname,以&开头),然后直接返回这个bean;
- 如果查询的name是一个普通的name,对应的bean可能也是factorybean,如果是普通的bean,那么就直接返回
- 如果是一个factorybean,先从对应的缓存加载,如果缓存没有,则直接从factorybean中创建
factorybean创建bean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (already There != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
代码里面写的很长,主要的工作就是getObject,从这个方法中获取bean对象,对于factorybean本身,spring容器中也有对应bean,但是获取的时候,只会获取对应的object对象
回到前面说的doGetbean方法的else部分,此时在缓存中并没有对应的bean,需要我们创建
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 (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
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);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
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);
}
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);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
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, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
上面的流程可以归纳为如下:
- 检查这个beandefinition有没有对应的parentfactory,如果有的话并且当前beanfactory中也没有对应的beandifinition,就用对应的factory创建。
- 检查当前获取bean是否是检查,如果是则直接返回
- 检查当前beandefinition的depend-on属性,如果有以来,则先实例化所有的依赖的bean
- 根据bean的属性是否是单例调用对应的createbean方法来实例化bean,然后再调用getObjectForBeanInstance来获取bean。
核心的方法在于createbean方法
createbean
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
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);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
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) {
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;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
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<>(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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
整个创建bean的流程还是比较清晰的,主要流程如下:
- 首先检查容器中是否有InstantiationAwareBeanPostProcessor,这个接口的实现类是用来给我们提供一个拓展能力,进行定制bean,查看这个接口可以自定义往容器中添加bean,这个是spring在实例化bean之前,最后一次修改bean的机会。
- 实例化bean,可以是根据构造函数创建,也可以是工厂方法创建
- 获取MergedBeanDefinitionPostProcessor实例,应用到该bean实例上,比如说我们的@PostConstructor的解析,@Resource,@Autowire 在这个阶段都有处理,注意这里只是做简单的检验等处理,并没有解析。
- populateBean,这个阶段处理的事情主要是bean的属性设置,包括xml中配置的属性设置,@Autowire方法的注入就是在这里做的,下面会分析源码。
- initializebean,初始化bean,这里主要包括Aware接口的调用,@PostConstruct初始化方法,InitializeBean接口的方法,xml中配置的init的处理方法。
先看下populateBean这个方法的源码
populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
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.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
- 先处理InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation,这个方法就是用来处理当前的bean的实例化有没有完成,如果完成了,那么就直接返回,目前还没有什么实现类做这个;
- 然后是根据Autowiredmode来处理,这里我们代码调试mode为AUTOWIRE_NO=0,什么意思呢,就是不会自动注入,但是显示的@Autowire方式还是会注入的。这里涉及到一个知识点就是AutowireCapableBeanFactory,默认的我们的bean的注入会根据bean中有@Autowire的时候会自动注入进来,没有这个注解的话,我们获取的bean中需要被注入的对象就是null,这个很好理解:A中依赖注入B,必须要显示在属性B对象上设置@Autowire,这样我们getbean A的时候里面的属性B才有,如果没有这个显示注解,属性B是null,但是如果我们getbean的方法换一种的话,我们是可以人为的帮A注入B对象,AutowireCapableBeanFactory beanFactory = context.getAutowireCapableBeanFactory();
A a = (A) beanFactory.autowire(A.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); B b = a.getB();这样就获取到B属性了。通过这种方式,可以人为的给A这个bean注入属性B了。 - 然后就是处理它的postProcessProperties方法,这个方法处理的就包含@Autowire的注入,而且还包含一些属性的设置,比如我们在xml中配置的属性值初始化,就是在这里完成的。
populatebean方法完成后,我们的依赖注入就完成了,前面createbean方法我们创建了bean对象,这里又设置了初始化属性值以及IOC依赖注入,接下来就是初始化这个bean了
initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
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()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
对于这个方法,不过多的讲细节了,注意下流程
- 首先是invokeAwareMethods方法调用,这个方法就是我们一系列的Aware接口,比如我们BeanNameAware,ApplicationContextAware就是在这个环节做的
- 然后是applyBeanPostProcessorsBeforeInitialization,这个是把所有的BeanPostProcessor里面的postProcessBeforeInitialization执行一遍,我们的@PostConstruct注解就是属于CommonAnnotationBeanPostProcessor这个processor然后被处理的
- 然后是invokeInitMethods,这个方法里面包含两部分,首先根据当前的bean有没有实现InitializingBean这个接口,如果实现了就会去执行这个接口的afterPropertiesSet方法进行初始化;然后再获取自定义的初始化方法,比如我们在xml中指定的init-Method方法,就会在这里被找出来。
所以我们这个的初始化流程就是
- 构造函数
- IOC依赖注入
- 初始化属性设置
- Aware钩子函数
- @PostConstruct注解初始化函数
- afterPropertiesSet初始化方法执行
- init-Method初始化方法执行。
到此,我们的spring的初始化流程讲完。