話說最近我們組瘋狂招人中,組裏的幾位資深大佬在瘋狂面試,從早到晚就是在語音和視頻,昨晚要加班,下樓跟大手子們去吃飯,聊起面試狀況,一位大佬VV哥開始瘋狂輸出:「我這面試一天,基本上沒幾個能把Spring的加載過程說清楚的,基本上一問就支支吾吾,如今這API調用工程師太多了」,另外一位大佬髒髒哥瘋狂附和,我在一邊聽到流下了沒有技術的「冷汗」,這......不就是說的我嘛,天天寫寫業務代碼,調調接口,寫寫SQL,搞搞TestCase,屬實是最底層的搬磚工,瘋狂扒拉兩口飯,立馬逃離大型審判現場,跑到工位坐下開始 看!源!碼!整活~菜狗要翻身!前端
那其實講到Spring,咱們能夠這麼看:java
由於Spring 最初利用「工廠模式」( DI )和「代理模式」( AOP )解耦應用組件。你們以爲挺好用,因而按照這種模式搞了一個 MVC 框架(一些用 Spring 解耦的組件),用開發 web 應用( SpringMVC)。而後呢,又發現每次開發都要搞不少依賴,寫不少樣板代碼很麻煩,那就很煩躁了,因而乎大牛們就搞了一些懶人整合包( starter ),這套玩意就是 Spring Boot ,具體介紹以下:
web
廢話很少說了,如今就跟你們來一次對Spring的源碼追蹤一波,本菜狗今天就要看一看Spring究竟是怎麼進行的初始化的,它如何建立的bean,咱們此次就從spring-boot-1.5.13進行追蹤一步步往下看吧;
面試
1.默認的spring啓動器,直接從這個地兒進去,沒毛病:spring
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}複製代碼
2.下面的代碼 new SpringApplication(sources).run(args) 建立了一個SpringApplication,執行了一個run方法,返回的是一個ConfigurableApplicationContext,這只是一個接口,根據他的命名來看的話,是一個可配置的應用上下文對象;緩存
下面的run方面看起來就是咱們要看的重點吧?Emmmm....不慌不慌,繼續往下點就完事了;bash
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified source using default settings.
* @param source the source to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[] { source }, args);
}
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param sources the sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}複製代碼
3.進去run方法後,哦豁,這一大堆玩意兒,也不知道這都是些啥,哎,硬着頭皮往下看吧,衝!兄弟們!app
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
//參數封裝,在命令行下啓動應用帶的參數
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}複製代碼
3.嗨呀,乍一看好像也就這麼些東西,核心的東西都在try{}裏面,咱們一個個看,前面幾行就是獲取args參數和準備獲取一些環境配置的東西,問題不大;
框架
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);複製代碼
4.接下來,嘿,好傢伙,開始建立context對象了,看到context = createApplicationContext這行;less
context = createApplicationContext();複製代碼
而後進入,由於咱們剛剛在建立ConfigurableApplicationContext時並無給 context賦值,因此此時context = null,那麼便會建立指定的兩個applicationContext中的一個,返回一個剛剛建立的context,這個context即是咱們的基礎,由於我們如今爲web環境,因此建立的context爲 AnnotationConfigEmbeddedWebApplicationContext。
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."
+ "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";
private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
複製代碼
5.這些事幹完以後,就到了準備上下文了;
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
複製代碼
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//設置context上下文的environment,簡單 設置環境相關的配置唄
context.setEnvironment(environment);
// 應用上下文後處理
postProcessApplicationContext(context);
//在context refresh以前,對其應用ApplicationContextInitializer
applyInitializers(context);
// 上下文準備(這個裏面是空實現,這是Spring預留擴展用的)
listeners.contextPrepared(context);
// 打印啓動日誌和啓動應用的Profile
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// Load the sources
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[sources.size()]));
listeners.contextLoaded(context);
}複製代碼
6.上面這些看無缺像也沒啥,接下來,重頭戲應該要來了吧;
refreshContext(context);複製代碼
這個方法好像有點狠,看着架勢是用來準備容器和刷新應用上下文的,我們點進去看看;
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}複製代碼
誒,還有個方法,繼續點進去;
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}複製代碼
Emmmmm...乖乖,都是AbstractApplicationContext.class是這個玩意在從中做梗,我們繼續進去!衝!
PS:只要咱們進入了refresh(context)這個方法,無論進入哪個實現類,最終進入的都是AbstractApplicationContext.java這個類:
來到了咱們的核心,AbstractApplicationContext類,refresh方法就很貼心,裏面每一個方法幹了啥都有註釋,這就很舒服,減小了我們理解的難度(這時候坐我旁邊的粉粉同窗看到了就開始小聲bb:這英文註釋就很煩,在下立馬強勢回懟:快,趕忙裝個翻譯插件去,快,跑步前進~);
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//初始化一些配置屬性,驗證配置文件
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//簡單的獲取beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//將context中的一些屬性設置到beanFactory中
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//這個地方空實現,也沒幹啥,Spring預留的擴展
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//解析配置文件、生成全部的beanDefinitions
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//分類、排序、註冊(注入)全部的BeanPostProcessors,用於處理 bean 的初始化流程
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//這玩意就是用來作國際化的
initMessageSource();
// Initialize event multicaster for this context.
//註冊 applicationEventMulticaster SingletonBean
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//這裏主要建立和初始化容器
onRefresh();
// Check for listener beans and register them.
//檢查監聽器bean並註冊它們
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//主要是初始化非懶加載單例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//大功告成,而後開啓Web容器
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(); } } }複製代碼
上面這些代碼總結一波:
其實上面的方法中,咱們須要比較注意的地方有兩個,其實加載bean主要是在這兩個方法裏面取作的,咱們看代碼:
1.invokeBeanFactoryPostProcessors(beanFactory);
2.finishBeanFactoryInitialization(beanFactory);
咱們進入invokeBeanFactoryPostProcessors,而後繼續走着,找到這一行
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());複製代碼
而後繼續在這個方法中找到
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);複製代碼
進入到該方法內部裏面以後,有一個循環,進入內部方法 :
postProcessor.postProcessBeanDefinitionRegistry(registry)
此時傳入的registry就是咱們context中的beanfactory,由於其實現了BeanDefinitionRegistry接口,而此時的postProcessor實現類爲ConfigurationClassPostProcessor.java
/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@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);
}複製代碼
進入以後直接看最後面的一個方法,名稱爲processConfigBeanDefinitions(registry),翻譯一波就是用來配置beanDefinitions的流程。
OK,咱們繼續點進去,這裏代碼過於長,我們就不貼了8~~~(偷一波懶);
在processConfigBeanDefinitions(registry)裏,在301行代碼會獲取一個解析器,代碼以下:
ConfigurationClassParser parser = new ConfigurationClassParser( --301行
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);複製代碼
parser.parse(candidates); --308行複製代碼
而後308行會執行parser的parse方法,進入parse方法以後,會發現內層還有parse方法,沒關係,繼續進入內層的parse,而後發現有個for循環;
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}複製代碼
protected final void parse(String className, String beanName) throws IOException {
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
processConfigurationClass(new ConfigurationClass(reader, beanName));
}
protected final void parse(Class<?> clazz, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(clazz, beanName));
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}複製代碼
注意!這裏有3個parse方法,每一個方法裏面都執行了下面這個方法;
processConfigurationClass(new ConfigurationClass(metadata, beanName));
複製代碼
而後咱們繼續往下走,在processConfigurationClass(ConfigurationClass configClass)方法內,有一個do循環
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}複製代碼
咱們繼續進去看看,這個時候,出現了許多咱們經常使用的註解,Spring會找到這些註解,並對它們進行解析。咱們看代碼:
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());
}
}
}複製代碼
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());複製代碼
進入 this.componentScanParser.parse,直接進入結尾的scannner.doScan
return scanner.doScan(StringUtils.toStringArray(basePackages));
而後就會開始掃描basePackages,並將掃描到的bean生成一個一個BeanDefinitionHolder,BeanDefinitionHolder中包含有咱們bean的一些相關信息、以及Spring賦予其的額外信息
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);
}
}
}複製代碼
而後就開始調用以下方法將bean註冊到BenFactory中!
registerBeanDefinition(definitionHolder, this.registry);複製代碼
OK,註冊完後,invokeBeanFactoryPostProcessors(beanFactory)這個方法也算是使命結束,這個時候咱們直接跳到finishBeanFactoryInitialization(beanFactory)這個方法,咱們點進去:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
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));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}複製代碼
到這個階段了,咱們要開始建立bean的實例了,咱們找到下面的代碼:
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}複製代碼
進入getBean!
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}複製代碼
再進getBean
@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;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance: // We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final 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, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
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(); 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; } } // Check if required type matches the type of the actual bean instance. 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; }複製代碼
而後咱們繼續哐哐哐往下整吧(任重道遠啊!好多層!)
從上面的代碼找到這一行,看名字就是建立Bean,咱們繼續點進去
prototypeInstance = createBean(beanName, mbd, args);複製代碼
這個方法進去後,找到下面這行,繼續進去(要瘋了,兄弟們)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
複製代碼
OKKKKK,這個進去後還有,找到下面代碼:
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}複製代碼
而後再進入createBeanInstance方法,找到下面的代碼
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}複製代碼
進入autowireConstructor(很明顯,註解構造器),而後.....Emmm....裏面還有,咱們在裏面找到下面這段代碼:
if (System.getSecurityManager() != null) {
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
}
}, beanFactory.getAccessControlContext());
}
else {
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}複製代碼
啥也別說了,繼續進入這個方法,好像到一個工具類了,看到但願了!!!
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
if (bd.getMethodOverrides().isEmpty()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
ReflectionUtils.makeAccessible(ctor);
return null;
}
});
}
return BeanUtils.instantiateClass(ctor, args);
}
else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}複製代碼
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}複製代碼
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}複製代碼
感動落淚,終於到了Spring bean加載的核心了!對!反射!咱們最後會發現是經過反射newInstance取得的對象實例:
獲取到對象實例以後,咱們要幹啥?填充一波 調用populateBean方法!
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}複製代碼
繼續點進去,進入後便能看到和咱們平時代碼對應的條件了,例如byType注入、byName注入:
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}複製代碼
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}複製代碼
這個時候,這一行代碼,就是進行依賴注入的地方了!
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);複製代碼
這個時候,咱們一點,發現有不少實現類,感受咱們平時項目裏面@Autowired註解用得多一點,咱們就選AutowiredAnnotationBeanPostProcessor這個類吧,點開看看:
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;複製代碼
看findAutowiringMetadata這個方法名應該是獲取元信息,獲取完後,再調用:
metadata.inject(bean, beanName, pvs);複製代碼
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}複製代碼
激動啊,這個莫非就是傳說中替咱們作的set方法??最後完成注入?
field.set(bean, value);
寫完這個以後,整體對Spring加載的過程有了更深刻的理解,在看源碼的過程當中,也有不少本身不理解的東西,也綜合了不少信息來幫忙本身理解和完成此次文章,相信大哥們看完可能會發現一些錯誤或者理解不一致處,歡迎指出,共同進步!