docs/Spring全家桶/Spring源码分析/Spring组件分析/Spring组件之ApplicationContext.md
ApplicationContextspring ʱһ
ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
ApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(MvcConfig.class);
context.refresh();
AnnotationConfigApplicationContext AnnotationConfigWebApplicationContext ApplicationContextսл AbstractApplicationContext#refresh spring
ApplicationContext Ϊ spring ӦԻȡ spring ڼĸϢ BeanFactory``Environment ȣ spring Ҫһࡣ
ApplicationContext ̳еĽӿ£
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory,
HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher,
ResourcePatternResolver {
...
}
ԿApplicationContext ҲӿڵӽӿڣЩӿڵĹ£
EnvironmentCapableṩ˻ùܣapplicationContext ʵлһ Environment ͵ijԱͨ EnvironmentCapable#getEnvironment() ȡListableBeanFactory``BeanFactory ӽӿڣṩо BeanFactory bean ķHierarchicalBeanFactory``BeanFactory ӽӿڣṩ BeanFactory Ƽ̳еԻȡ BeanFactoryMessageSourceָϢԴʵֹʻApplicationEventPublisher¼ṩ publishEvent(...) ¼ResourcePatternResolverԴṩ˻ȡԴResourceķgetResources(...)ApplicationContext ṩķ
Կķࡣ
ApplicationContext ̳нṹApplicationContext УApplicationContext ҪΪϵǼ£
ApplicationContextͨ java Ӧõ ApplicationContextΪ AnnotationConfigApplicationContextApplicationContext web Ӧõ ApplicationContextΪ AnnotationConfigWebApplicationContextֻ servlet ͵ web reactive webAnnotationConfigApplicationContext ļ̳нṹ
AnnotationConfigWebApplicationContext ļ̳нṹ
ApplicationContextspring bean лȡ ApplicationContextͨ ApplicationContextAware ӿ
@Component
public class TestBean implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
//
}
̳ ApplicationContextAware ApplicationContextAwareProcessor ڳʼɺ setApplicationContext(xxx) ֻҪ TestBean άһԱ applicationContext 漴ɡ
ApplicationContextAwareProcessorApplicationContextAwareProcessor һ BeanPostProcessorҪע ApplicationContextAwareProcessor#postProcessBeforeInitialization £
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
/**
* applicationContext EnvironmentResourceLoader
* ApplicationEventPublisherMessageSource ȵ࣬Щawareӿڵĵã
* ͨ applicationContext
*/
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
/**
* Aware ӿڵķ
* EmbeddedValueResolverAware⣬Ĵ this.applicationContext
*/
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
// עembeddedValueResolverĻȡ£
// new EmbeddedValueResolver(applicationContext.getBeanFactory());
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(
this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
// װ ʵApplicationContextAware applicationContext
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
DZȽϼģж bean ͣȻת÷
ApplicationContext BeanFactory ĹϵApplicationContext BeanFactory ߵĹϵһʼ˵ ApplicationContext ̳ BeanFactory ĽӿڣΪǼ̳йϵ˼̳йϵ⣬ǻϹϵApplicationContext BeanFactory Ķֱӿ룺
AnnotationConfigApplicationContext``beanFactory ֵ£
public class GenericApplicationContext extends AbstractApplicationContext
implements BeanDefinitionRegistry {
// dzе beanFactory
private final DefaultListableBeanFactory beanFactory;
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
...
}
AnnotationConfigWebApplicationContext``beanFactory ֵ£
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
// dzе beanFactory
@Nullable
private DefaultListableBeanFactory beanFactory;
@Override
protected final void refreshBeanFactory() throws BeansException {
// жϵǰApplicationContextǷBeanFactoryڵĻ Beanر BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// ʼDefaultListableBeanFactoryĴ
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// BeanFactory ԣǷ Bean ǡǷѭ
customizeBeanFactory(beanFactory);
// Bean BeanFactory
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
...
}
}
// beanFactory
protected DefaultListableBeanFactory createBeanFactory() {
// ָbeanFactory
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
// ȡ beanFactory
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
...
}
return this.beanFactory;
}
}
...
}
BeanFactory طʵ£
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {### 1\. ʲô `BeanDefinition`
`BeanDefinition` `bean` spring bean Ϣ
java УһԪϢ췽ԱԱȣʹõ `Class` ࣬һ`.class` ļص jvm һ `Class` ڶʵʱ `Class` Ϣɡ
spring УҲôһ bean Ϣ `BeanDefinition` spring bean ɣγʼٵȣֵ֧IJַ
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* ø BeanDefinition
* BeanDefinition иƼ̳еĸָ˸BeanDefinition
* ʵbeanʱϲBeanDefinition
*/
void setParentName(@Nullable String parentName);
/**
* ȡBean
*/
@Nullable
String getParentName();
/**
* beanClass
* ʵʱʵ Class Ķ
*/
void setBeanClassName(@Nullable String beanClassName);
/**
* ȡbeanClass
*/
@Nullable
String getBeanClassName();
/**
* bean÷Χԭ
*/
void setScope(@Nullable String scope);
/**
* ȡbean÷Χԭ
*/
@Nullable
String getScope();
/**
*
*/
void setLazyInit(boolean lazyInit);
/**
* ǷΪ
*/
boolean isLazyInit();
/**
* øBeanBean
* @DependsOn ָbean
*/
void setDependsOn(@Nullable String... dependsOn);
/**
* ظBean
*/
@Nullable
String[] getDependsOn();
/**
* ǷΪԶעĺѡ
*/
void setAutowireCandidate(boolean autowireCandidate);
/**
* ǷΪԶעĺѡ
*/
boolean isAutowireCandidate();
/**
* ǷΪҪģдڶͬ͵beanʱֻҪ
* @Primary
*/
void setPrimary(boolean primary);
/**
* ǷΪҪbean
*/
boolean isPrimary();
/**
* factoryBean
* ָfactoryBean
*/
void setFactoryBeanName(@Nullable String factoryBeanName);
/**
* factoryBean
* ȡfactoryBean
*/
@Nullable
String getFactoryBeanName();
/**
* ù
* @Bean ǵķ
*/
void setFactoryMethodName(@Nullable String factoryMethodName);
/**
* ع
* @Bean ǵķ
*/
@Nullable
String getFactoryMethodName();
/**
* ȡȥIJֵ
*/
ConstructorArgumentValues getConstructorArgumentValues();
/**
* 췽Ƿв
*/
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
/**
* ȡֵ
* ֵΪ췽IJ
*/
MutablePropertyValues getPropertyValues();
/**
* Ƿֵ
*/
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
/**
* óʼ
*/
void setInitMethodName(@Nullable String initMethodName);
/**
* ȡʼ
*/
@Nullable
String getInitMethodName();
/**
* ٷ
*/
void setDestroyMethodName(@Nullable String destroyMethodName);
/**
* ȡٷ
*/
@Nullable
String getDestroyMethodName();
/**
* ǷΪbean
*/
boolean isSingleton();
/**
* ǷΪԭbean
*/
boolean isPrototype();
/**
* Bean DZΪ abstractôʵΪ bean ڼ̳
*/
boolean isAbstract();
...
}
Կ`BeanDefinition` ֵ֧ķdz࣬кܶƽʱʹʱָģ
* `setScope(...)` bean ÷Χ `@Scope` ָ
* `setLazyInit(...)`أ `@Lazy` ָ
* `setDependsOn(...)` bean `@DependsOn` ָ
* `setPrimary(...)`ΪҪ bean `@Primary` ָ
* `setFactoryMethodName(...)`ùƣ `@Bean` ǵķ
עʱָģЩ `xml` ʱָģ磺
* `setInitMethodName(...)`óʼ `init-method` ָ
* `setDestroyMethodName(...)`ٷ `destroy-method` ָ
### 2\. spring ṩЩ `BeanDefinition`
`BeanDefinition` һӿڣǵȻֱʹã Spring ṩЩ `BeanDefinition`

spring ṩ `BeanDefinition` ͼʾļˣҪ֣
* `RootBeanDefinition`
* `ChildBeanDefinition`
* `GenericBeanDefinition`
* `ScannedGenericBeanDefinition`
* `AnnotatedGenericBeanDefinition`
#### 2.1 `RootBeanDefinition` `ChildBeanDefinition`
ǰᵽ `BeanDefinition` ӵĸ̳еģһ˵ǿ `RootBeanDefinition` 幫Ȼ `ChildBeanDefinition` жԵݣʾ£
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // RootBeanDefinition RootBeanDefinition root = new RootBeanDefinition(); root.setBeanClass(User.class); root.getPropertyValues().add("name", "123"); // ע᷽չʾʵĿвʹ // ʹĿʹõ BeanDefinitionRegistryPostProcessor ṩķ context.registerBeanDefinition("root", root);
// ChildBeanDefinition
ChildBeanDefinition child1 = new ChildBeanDefinition("root");
child1.getPropertyValues().add("age", "11");
// ע᷽չʾʵĿвʹ
// ʹĿʹõ BeanDefinitionRegistryPostProcessor ṩķ
context.registerBeanDefinition("child1", child1);
// ChildBeanDefinition
ChildBeanDefinition child2 = new ChildBeanDefinition("root");
child2.getPropertyValues().add("age", "12");
// ע᷽չʾʵĿвʹ
// ʹĿʹõ BeanDefinitionRegistryPostProcessor ṩķ
context.registerBeanDefinition("child2", child2);
//
context.refresh();
User rootUser = (User) context.getBean("root");
User child1User = (User) context.getBean("child1");
User child2User = (User) context.getBean("child2");
System.out.println(rootUser);
System.out.println(child1User);
System.out.println(child2User);
}
н
User{name='123', age=null} User{name='123', age=11} User{name='123', age=12}
Կ`child1` `child1` гɹش `RootBeanDefinition` ̳еԡ
#### 2.2 `GenericBeanDefinition`
Ǹͨõ `BeanDefinition`ֱӼ̳ `AbstractBeanDefinition`ṩķ£

Կṩķ̳࣬ `AbstractBeanDefinition`һ£ҪԼ `BeanDefinition` ʱֻҪʹͿˣҲṩһʾ
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
GenericBeanDefinition userBeanDefinition = new GenericBeanDefinition();
userBeanDefinition.setBeanClass(User.class);
userBeanDefinition.getPropertyValues().add("name", "123");
userBeanDefinition.getPropertyValues().add("age", "11");
// ע᷽չʾʵĿвʹ
// ʹĿʹõ BeanDefinitionRegistryPostProcessor ṩķ
context.registerBeanDefinition("user", userBeanDefinition);
//
context.refresh();
User user = (User) context.getBean("user");
System.out.println(user);
}
### 2.3 `ScannedGenericBeanDefinition`
`ScannedGenericBeanDefinition` ̳ `GenericBeanDefinition`ͬʱҲʵ `AnnotatedBeanDefinition` ӿڣṩķࣺ

`GenericBeanDefinition`Ͳṩʾˡ
### 2.4 `AnnotatedGenericBeanDefinition`
`AnnotatedGenericBeanDefinition` ̳ `GenericBeanDefinition`ͬʱҲʵ `AnnotatedBeanDefinition` ӿڣṩķࣺ

`GenericBeanDefinition`Ͳṩʾˡ
### 3\. spring е `BeanDefinition`
Ӷ spring `BeanDefinition`Ҫβ spring е `BeanDefinition` أ
#### 3.1 demo
һ demo
`service`
@Service public class Service01 {
private String name;
public void hello() {
System.out.println("hello " + name + ", from service01");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Service public class Service02 {
private String name;
public void hello() {
System.out.println("hello " + name + ", from service02");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Ҫࣺ
@ComponentScan public class Demo02Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext();
context.register(Demo02Main.class);
context.refresh();
Service01 service01 = (Service01) context.getBean("service01");
Service02 service02 = (Service02) context.getBean("service02");
service01.hello();
service02.hello();
}
}
£
hello null, from service01 hello null, from service02
˵ǵѾɹˣ`service01` `service02` Ҳʼɹˡ
#### 3.2 ɹij
Ƿ£`service01` `service02` Ѿʼɹˣ˵бȻ `service01` `service02` Ӧ `beanDefifnition` `beanDefifnition`ͱҪȻȡ `beanDefifnition`
λȡ spring Ѿڵ `beanDefifnition` أο 2 ڵʾΪ `context.refresh()` ǰȡ
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Demo02Main.class); // ȡ beanDefinitionᱨ BeanDefinition service01Bd = context.getBeanDefinition("service01"); service01Bd.getPropertyValues().addPropertyValue("name", "123");
context.refresh();
Service01 service01 = (Service01) context.getBean("service01");
Service02 service02 = (Service02) context.getBean("service02");
service01.hello();
service02.hello();
}
Уֻᱨ
Exception in thread "main" org.springframework.beans.factory .NoSuchBeanDefinitionException: No bean named 'service01' available
㣬һ뵽 `context.refresh()` ǰȡᱨ֮أ
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Demo02Main.class); context.refresh();
// ȡ beanDefinitionIJ
BeanDefinition service01Bd = context.getBeanDefinition("service01");
service01Bd.getPropertyValues().addPropertyValue("name", "123");
Service01 service01 = (Service01) context.getBean("service01");
Service02 service02 = (Service02) context.getBean("service02");
service01.hello();
service02.hello();
}
У£

ȷʵûбǵҲûáڴǸ `service01` `name` ֵָΪ `123`н `null`ûõԭ `service01` `context.refresh()` гʼ ģô `BeanDefinition` ģҲֲϡ
ôҪôأ
#### 3.2 `BeanDefinitionRegistryPostProcessor`ƻ `beanDefinition`
Ҫųˣоǣ`BeanFactoryPostProcessor`ĽܣĽܣԲο [spring ֮ BeanFactoryPostProcessor](https://my.oschina.net/funcy/blog/4597545)ֱӸ½ۣ
> `BeanFactoryPostProcessor` `spring beanFactory ĺô`ƻ `beanFactory` һЩΪspring Ϊṩ `BeanFactoryPostProcessor`
>
> * `BeanFactoryPostProcessor`ƻ `beanFactory` Ϊ
> * `BeanDefinitionRegistryPostProcessor`ƻ `beanDefinition` Ϊ
ԣӦʹ `BeanDefinitionRegistryPostProcessor`ֱʵӿڣ
@Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
BeanDefinition service01Bd = registry.getBeanDefinition("service01");
service01Bd.getPropertyValues().addPropertyValue("name", "123");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
// BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor ӽӿ
// postProcessBeanFactory(...) BeanFactoryPostProcessorﲻ
}
}
`main` һ£
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Demo02Main.class); context.refresh();
Service01 service01 = (Service01) context.getBean("service01");
Service02 service02 = (Service02) context.getBean("service02");
service01.hello();
service02.hello();
}
У£
hello 123, from service01 hello null, from service02
Կ `service01` `name` ȷʵ `123` ˡ
ʵϣ`BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry` Ҫʹ `BeanDefinitionRegistry` `BeanDefinition` IJֵ֧ķ£

Ҫ£
* `getBeanDefinition(...)`ȡ `BeanDefinition`أõ `BeanDefinition` ͿԶиֲ
* `registerBeanDefinition(...)`ע `BeanDefinition`Զ `BeanDefinition` Ȼø÷עᵽУǰУ `context.refresh()` ǰ `context.registerBeanDefinition`Ҫ˵ǰķɣе£õ `context.refresh()` `context` `springboot` УƼʹ `BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry` ע `BeanDefinition`
* `removeBeanDefinition(...)`Ƴ `BeanDefinition`һӦòõ
* `containsBeanDefinition(...)`жǷij `BeanDefinition`
### 4\. ܽ
Ҫ `BeanDefinition` ã
1. `BeanDefinition` ķ
2. ͵ `BeanDefinition` ʹ
3. ʹ `BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry` `BeanDefinition`Ҫעᡢ `BeanDefinition`
* * *
_ԭӣ[https://my.oschina.net/funcy/blog/4597536](https://my.oschina.net/funcy/blog/4597536) ߸ˮƽд֮ӭָԭףҵתϵȨҵתע_
...
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType, args);
}
...
}
Щʵʱǵ getBeanFactory() ȡ BeanFactory Ȼֱӵ BeanFactory ķgetBeanFactory() õľ GenericApplicationContext AnnotationConfigWebApplicationContext getBeanFactory()
ApplicationContext ݾͽܵˡ
ԭӣhttps://my.oschina.net/funcy/blog/4597456 ߸ˮƽд֮ӭָԭףҵתϵȨҵתע