首先看一下类的注释和翻译
/**
* {@link ServletWebServerApplicationContext} that accepts annotated classes as input - in
* particular {@link org.springframework.context.annotation.Configuration @Configuration}
* -annotated classes, but also plain {@link Component @Component} classes and JSR-330
* compliant classes using {@code javax.inject} annotations. Allows for registering
* classes one by one (specifying class names as config location) as well as for classpath
* scanning (specifying base packages as config location).
* <p>
* Note: In case of multiple {@code @Configuration} classes, later {@code @Bean}
* definitions will override ones defined in earlier loaded files. This can be leveraged
* to deliberately override certain bean definitions via an extra Configuration class.
*
* @author Phillip Webb
* @see #register(Class...)
* @see #scan(String...)
* @see ServletWebServerApplicationContext
* @see AnnotationConfigWebApplicationContext
*/
中文:
ServletWebServerApplicationContext接受带注释的类(特别是@Configuration带注释的类)作为输入,但也可以使用javax.inject注释将普通的@Component类和符合JSR-330的类作为输入。
允许一对一注册类(将类名指定为配置位置),以及进行类路径扫描(将基本包指定为配置位置)。
注意:如果有多个@Configuration类,则以后的@Bean定义将覆盖在先前加载的文件中定义的定义。可以利用此属性通过一个额外的Configuration类来故意覆盖某些Bean定义。
类图继承关系如下:
类图上发现,它既是BeanFactory,又是BeanDefinitionRegistry,还是ApplicationEventPublisher, 整个spring所存放的资源,几乎都在这里了。放在下面讲解。
何时创建了这个ApplicationContext呢?
SpringApplication类中的run方法中调用
context = createApplicationContext();
就是通过反射,调用了AnnotationConfigServletWebServerApplicationContext的无参构造方法
/**
* Create a new {@link AnnotationConfigServletWebServerApplicationContext} that needs
* to be populated through {@link #register} calls and then manually
* {@linkplain #refresh refreshed}.
*/
//springboot创建ApplicationContext的时候就是通过反射,调用的这个构造方法
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
1. 在初始化父类GenericApplicationContext的时候,创建了IOC极重要的BeanFactory---DefaultListableBeanFactory
/**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
2. 构造方法中,初始化了AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,(这两个类内部初始化了哪些东西,此处不叙)
3. ApplicationContext怎么还是BeanDefinitionRegistry呢?(先说答案,初始化了DefaultListableBeanFactory,BeanDefinitionRegistry自然就有了)
3.1 首先看BeanDefinitionRegistry是什么
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);
}
可见,BeanDefinitionRegistry是用来注册BeanDefinition的,多说一句,所有的BeanDefinition最终都是在BeanFactory (DefaultListableBeanFactory的beanDefinitionMap属性)里存放,
3.2 这些接口方法在ApplicationContext是在哪里实现的呢?
a) 从类图上看出AnnotationConfigServletWebServerApplicationContext父类GenericApplicationContext继承BeanDefinitionRegistry接口,
b) 且GenericApplicationContext 并非抽象类,故而必须在此类中实现接口中的方法。实现方式如下:
@Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
this.beanFactory.removeBeanDefinition(beanName);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
return this.beanFactory.getBeanDefinition(beanName);
}
@Override
public boolean isBeanNameInUse(String beanName) {
return this.beanFactory.isBeanNameInUse(beanName);
}
@Override
public void registerAlias(String beanName, String alias) {
this.beanFactory.registerAlias(beanName, alias);
}
@Override
public void removeAlias(String alias) {
this.beanFactory.removeAlias(alias);
}
@Override
public boolean isAlias(String beanName) {
return this.beanFactory.isAlias(beanName);
}
c) 由此可见,AnnotationConfigServletWebServerApplicationContext父类继承BeanDefinitionRegistry,并最终是调用了beanFactory的相关方法来实现的。
4. ApplicationContext怎么还是BeanFactory呢?
4.1 首先看一下BeanFactory是什么
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
可见BeanFactory是用来获取Bean对象,检查Bean对象等操作
4.2 这些接口方法在ApplicationContext是在哪里实现的呢?
AnnotationConfigServletWebServerApplicationContext的父类中抽象类AbstractApplicationContext 实现了BeanFactory接口中的方法,
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, requiredType);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, args);
}
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
getBeanFactory()方法是ConfigurableApplicationContext接口中的方法,AbstractApplicationContext通过此方法调用子类中的BeanFactory的getBean等方法,多说一句,其实IOC的单例bean,都在BeanFactory(DefaultListableBeanFactory)的父类DefaultSingletonBeanRegistry中的singletonObjects属性存放