The relationship between BeanFactory and ApplicationContext from the perspective of source code

Keywords: Java Spring

Hello, everyone. I'm Xiaohei. This is the last tweet before this year. I wish you a happy new year in advance~~

This time, we will talk about the relationship between BeanFactory and ApplicationContext from the perspective of source code, and talk about some points that are not mentioned in the online article.

Official description

Let's take a look at the descriptions of BeanFactory and ApplicationContext in the official documents.

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.

https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-beanfactory

We can learn from the official documents:

The BeanFactory interface provides an advanced configuration mechanism that can manage objects of any type.

ApplicationContext is a sub interface of BeanFactory, which adds the following functions:

  • Easier integration with Spring's AOP
  • Message resource processing for Internationalization
  • Event Publishing
  • Context specific to the application layer, such as the WebApplicationContext for web applications.

Brief analysis of source code

The following source code is based on spring version 5.0.13.

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver
public interface ListableBeanFactory extends BeanFactory

It can be confirmed from the source that ApplicationContext inherits 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);
        // false
        System.out.println(context == bean.beanFactory);
        context.close();
    }
}

Annotationconfidapplicationcontext is an implementation class of ApplicationContext. In other words, annotationconfidapplicationcontext is also an implementation class of BeanFactory.

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

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

BeanFactory and ApplicationContext

There is a getBeanFactory method in the annotationconfigpplicationcontext.

To be exact, it is 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);
        // true
        System.out.println(context.getBeanFactory() == bean.beanFactory);
        context.close();
    }
}

AbstractApplicationContext is an abstract implementation of ApplicationContext.

Annotationconfigpplicationcontext inherits GenericApplicationContext, and GenericApplicationContext inherits AbstractApplicationContext.

In AbstractApplicationContext, the implementation of all BeanFactory interfaces is delegated to BeanFactory objects.

// 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);
}
// AbstractApplicationContext#getBeanFactory
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

getBeanFactory() is an abstract method.

GenericApplicationContext implements this abstract method:

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

    private final DefaultListableBeanFactory beanFactory;
    ...
    public final ConfigurableListableBeanFactory getBeanFactory() {
        return this.beanFactory;
    }
    ...
}

summary

ApplicationContext is a sub interface of BeanFactory, but the instance objects of ApplicationContext and BeanFactory are not the same.

In the implementation of ApplicationContext, there is a member variable DefaultListableBeanFactory beanFactory. All functions related to BeanFactory interface are delegated to this member variable.

The beanfactory member variable in the ApplicationContext implementation class and the beanfactory in the container are the same instance object.

Posted by jehardesty on Mon, 13 Jan 2020 22:06:57 -0800