Back to Javatutorial

Spring组件之ApplicationContext

docs/Spring全家桶/Spring源码分析/Spring组件分析/Spring组件之ApplicationContext.md

1.0.020.6 KB
Original Source

1. ApplicationContext

spring ʱһ

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 Ƽ̳еԻȡ BeanFactory
  • MessageSourceָϢԴʵֹʻ
  • ApplicationEventPublisher¼ṩ publishEvent(...) ¼
  • ResourcePatternResolverԴṩ˻ȡԴResourceķgetResources(...)

ApplicationContext ṩķ

Կķࡣ

2. ApplicationContext ̳нṹ

ApplicationContext УApplicationContext ҪΪϵǼ£

  • web ͵ ApplicationContextͨ java Ӧõ ApplicationContextΪ AnnotationConfigApplicationContext
  • web ͵ ApplicationContext web Ӧõ ApplicationContextΪ AnnotationConfigWebApplicationContextֻ servlet ͵ web reactive web

AnnotationConfigApplicationContext ļ̳нṹ

AnnotationConfigWebApplicationContext ļ̳нṹ

3. bean лȡ ApplicationContext

spring 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 漴ɡ

4. ApplicationContextAwareProcessor

ApplicationContextAwareProcessor һ 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 ͣȻת÷

5. 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`

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/up-49cbc9cb32badc1db52717cd19a9447eca7.png)

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`ṩķ£

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/up-5ed980070b301dc84926fac2494093d4fc6.png)

Կṩķ̳࣬ `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` ӿڣṩķࣺ

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/up-9ed3925090a9ae5fc1d4218ed5a59c2ea19.png)

 `GenericBeanDefinition`Ͳṩʾˡ

### 2.4 `AnnotatedGenericBeanDefinition`

`AnnotatedGenericBeanDefinition` ̳ `GenericBeanDefinition`ͬʱҲʵ `AnnotatedBeanDefinition` ӿڣṩķࣺ

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/up-b2e7f49fcdcae4f7272e2670b4fbb92766a.png)

 `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();

// ȡ beanDefinition޸IJ
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();

}


У£

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/up-268bb546197c4eb9d1686118a12fabb0009.png)

ȷʵûбǵ޸ҲûáڴǸ `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ֵ֧ķ£

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/up-5812a2cac994c5940d57c7e6ab55c23a63e.png)

Ҫ£

*   `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 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע