Load bean definitions

In this step, all the configuration files--@Configuration classes or XML files-are processed. For Annotation-based configuration, all the classes annotated with @Components are scanned to load the bean definitions. All XML files are parsed, and the bean definitions are added to a BeanFactory. Each bean is indexed under its id. Spring provides multiple BeanFactoryPostProcessor beans, so, it is invoked to resolve runtime dependencies such as reading values from external property files. In a Spring application, BeanFactoryPostProcessor can modify the definition of any bean. The following diagram describes this step:

As shown in the preceding diagram, Spring first loads the bean definitions, and then calls BeanFactoryProcessor for some beans to modify its definitions accordingly. Let's see this with an example. We have two configuration files--AppConfig.java and InfraConfig.java, which are defined as follows:

  • Following is the AppConfig.java file:
        @Configuration 
        public class AppConfig { 
          @Bean 
          public TransferService transferService(){ ... } 
          @Bean 
          public AccountRepository accountRepository(DataSource 
dataSource){ ... } }
  • Following is the InfraConfig.java file:
        @Configuration 
        public class InfraConfig { 
          @Bean 
          public DataSource dataSource () { ... } 
        } 

These Java configuration files are loaded by the ApplicationContext to the container, and indexed with its id, as shown in the following diagram:

In the last diagram, Spring beans are indexed under its IDs into Spring's BeanFactory, and then, that BeanFactory object is passed as an argument to the postProcess() method of BeanFactoryPostProcessor. The BeanFactoryPostProcessor can modify the bean definition for some beans; this depends on the bean configurations provided by the developer. Let's see how BeanFactoryPostProcessor works, and how to override it in our application:

  1. BeanFactoryPostProcessor works on the bean definitions or the configuration metadata of the bean before the beans are actually created.
  2. Spring provides several useful implementations of BeanFactoryPostProcessor, such as reading properties and registering a custom scope.
  3. You can write your own implementation of the BeanFactoryPostProcessor interface.
  4. If you define a BeanFactoryPostProcessor in one container, it will only be applied to the bean definitions in that container.

The following is the code snippet for BeanFactoryPostProcessor:

    public interface BeanFactoryPostProcessor { 
      public void postProcessBeanFactory
(ConfigurableListableBeanFactory
beanFactory); }

Let's now see the following examples of the BeanFactoryPostProcessor extension point:

Reading external property files (database.properties)

Here, we'll use the DataSource bean to be configured with the database values such as username, password, db url, and driver, as follows:

    jdbc.driver=org.hsqldb.jdbcDriver 
    jdbc.url=jdbc:hsqldb:hsql://production:9002 
    jdbc.username=doj 
    jdbc.password=doj@123 

The following is the DataSource bean definition in the configuration file:

    @Configuration 
    @PropertySource ( "classpath:/config/database.properties" ) 
    public class InfraConfig { 
     @Bean 
     public DataSource dataSource( 
     @Value("${jdbc.driver}") String driver, 
     @Value("${jdbc.url}") String url, 
     @Value("${jdbc.user}") String user, 
     @Value("${jdbc.password}") String pwd) { 
       DataSource ds = new BasicDataSource(); 
       ds.setDriverClassName( driver); 
       ds.setUrl( url); 
       ds.setUser( user); 
       ds.setPassword( pwd )); 
       return ds; 
    } 
   } 

So, in the preceding code, how do we resolve the @Value and ${..} variables? We need a PropertySourcesPlaceholderConfigurer to evaluate them. This is a BeanFactoryPostProcessor. If you are using the XML configuration, the <context:property-placeholder/> namespace creates a PropertySourcesPlaceholderConfigurer for you.

Loading the bean definition is a one-time process at the time of loading the configuration file, but the initializing phase for bean instances is executed for each bean in the container. Let's have a look at the initialization of bean instances in the application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset