简体   繁体   中英

Short way of making many beans depend-on one bean

When using database migrations, I obviously want none of the DAOs to be usable before the migrations are run.

At the moment I'm declaring a lot of DAOs, all having a depends-on=databaseMigrator property. I find this troubling, especially since it's error prone.

Is there a more compact way of doing this?


Notes:

I do this on application start-up. The schema version that the application requires is compiled into the application as part of the build process. It is also stored in the database and updated by the database migration scripts.

On application start-up, the app checks that the schema version in the database is what it expects and if not, aborts immediately with a clear error message.

In a normal Java program, this happens right at the start of the main method.

In a webapp, it's performed by the app's ServletContextListener and is the first thing it does when the servlet context is created.

That's saved my (apps') bacon several times.

You could try writing a class that implements the BeanFactoryPostProcessor interface to automatically register the dependencies for you:

Warning: This class has not been compiled.

public class DatabaseMigratorDependencyResolver implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        String[] beanNames = beanFactory.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);

            // Your job is here:
            // Feel free to make use of the methods available from the BeanDefinition class (http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/config/BeanDefinition.html)
            boolean isDependentOnDatabaseMigrator = ...;

            if (isDependentOnDatabaseMigrator) {
                beanFactory.registerDependentBean("databaseMigrator", beanName);
            }
        }
    }

}

You could then include a bean of this class alongside all your other beans.

<bean class="DatabaseMigratorDependencyResolver"/>

Spring will automatically run it before it starts initiating the rest of the beans.

I ended up creating a simple ForwardingDataSource class which appears in the context files as:

<bean id="dataSource" class="xxx.ForwardingDataSource" depends-on="databaseMigrator">
   <property name="delegate">
      <!-- real data source here -->
   </property>
</bean>

If find it less elegant than Adam Paynter's solution , but clearer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM