Hi, I’m Xiao Hei. This is my last tweet before the New Year. Happy New Year to you all in advance

This time we will talk about the relationship between BeanFactory and ApplicationContext from a source point of view, and cover some points not mentioned in the web article.

The official description

Take a look at the official documentation for BeanFactory and ApplicationContext.

The org. Springframework. Beans and org. Springframework. Context packages are The basis for Spring Framework ‘s IoC container. The BeanFactoryinterface provides an advanced configuration mechanism capable of managing any type of object.ApplicationContextis a sub-interface ofBeanFactory. It adds:

  • Easier integration with Spring’s AOP features

  • Message resource handling (for use in internationalization)

  • Event publication

  • Application-layer specific contexts such as the WebApplicationContext for use in web applications.

Docs. Spring. IO/spring/docs…

From the official documents, we can learn:

The BeanFactory interface provides an advanced configuration mechanism for managing any type of object.

ApplicationContext is a subinterface of the BeanFactory, which adds the following functionality:

  • Easier integration with Spring’s AOP
  • Message resource processing for internationalization
  • Event publishing
  • Application-specific context, such as for Web applicationsWebApplicationContext.

Source analysis

The following source code is based on Spring 5.0.13.

public interface ApplicationContext extends EnvironmentCapable.ListableBeanFactory.HierarchicalBeanFactory.MessageSource.ApplicationEventPublisher.ResourcePatternResolver
Copy the code
public interface ListableBeanFactory extends BeanFactory
Copy the code

As evidenced by the source code, ApplicationContext inherits the BeanFactory.

@Configurable
public class Main {

    @Autowired
    BeanFactory beanFactory;

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
        Main bean = context.getBean(Main.class);
        // falseSystem.out.println(context == bean.beanFactory); context.close(); }}Copy the code

AnnotationConfigApplicationContext ApplicationContext is an implementation class, in other words, is the BeanFactory AnnotationConfigApplicationContext an implementation class.

However, running the above code, system.out.println (context == bean.beanFactory); The output is false.

Does this mean that ApplicationContext and BeanFactory are two different instance objects in the container?

The BeanFactory and ApplicationContext

In AnnotationConfigApplicationContext have a getBeanFactory method.

Precisely, is the org. Springframework. Context. Support. AbstractApplicationContext# getBeanFactory.

@Configurable
public class Main {

    @Autowired
    BeanFactory beanFactory;

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
        Main bean = context.getBean(Main.class);
        // false
        System.out.println(context == bean.beanFactory);
        // trueSystem.out.println(context.getBeanFactory() == bean.beanFactory); context.close(); }}Copy the code

Abstract implementation of AbstractApplicationContext is ApplicationContext.

AnnotationConfigApplicationContext inherited GenericApplicationContext, and GenericApplicationContext inherited AbstractApplicationContext again.

In AbstractApplicationContext, all the BeanFactory interface implementation, are entrusted to the BeanFactory object.

// AbstractApplicationContext#getBean(java.lang.Class<T>, java.lang.Object...)
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
  assertBeanFactoryActive();
  return getBeanFactory().getBean(requiredType, args);
}
Copy the code
// AbstractApplicationContext#getBeanFactory
public abstract ConfigurableListableBeanFactory getBeanFactory(a) throws IllegalStateException;
Copy the code

GetBeanFactory () is an abstract method.

GenericApplicationContext implements the abstract method:

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

	private finalDefaultListableBeanFactory beanFactory; .public final ConfigurableListableBeanFactory getBeanFactory(a) {
		return this.beanFactory; }... }Copy the code

conclusion

ApplicationContext is a subinterface of BeanFactory, but the instance object of ApplicationContext is not the same as the instance object of BeanFactory.

In the implementation of ApplicationContext, have a member variable DefaultListableBeanFactory the beanFactory, all related to the beanFactory interface function is delegated to the member variables.

The beanFactory member variable in the ApplicationContext implementation class is the same instance object as the beanFactory member in the container.