简体   繁体   中英

Spring Configuration creating two beans instead of one

I'm writing a RESTful web service using Spring MVC, using Java Configuration. My configuration file is below. My issue is this -- I discovered that 2 instances of "myService" bean is being created, instead of just one instance. I'm not sure why? How can I adjust the configuration to create only one?

Can anyone point me in the right direction? Thanks!

Here's my configuration class....

@Configuration
public class MyConfig {

    @Bean(name = "dataSource")
    public DriverManagerDataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        // datasource set up    
        return dataSource;
    }

    @Autowired
    @Bean(name = "sessionFactory")
    public SessionFactory getSessionFactory(DriverManagerDataSource dataSource) {
        LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
        sessionBuilder.scanPackages("com.mypackages");
        sessionBuilder.addProperties(getHibernateProperties());
        return sessionBuilder.buildSessionFactory();
    }

    private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.show_sql", "true");
        properties.put("hibernate.enable_lazy_load_no_trans", "true");
        properties.put("hibernate.id.new_generator_mappings", "true");
        return properties;
    }

    @Autowired
    @Bean(name = "transactionManager")
    public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);    
        return transactionManager;
    }

    @Bean
    public MyMainBean MyMainBean() {
        MyMainBean bean = new MyMainBean();
        bean.setService(myService());
        bean.setValidator(myValidator());
        return bean;
    }

    @Bean(name = "myService")
    public MyService myService() {
        MyService s = new MyService();
        s.setDao1(myDao1());        
        s.setDao2(myDao2());
        s.setCopyUtil(copyUtil());
        return s;
    }

    @Bean
    public MyDao1 myDao1() {
        return new MyDao1();
    }

    @Bean
    public MyDao2 myDao2() {
        return new MyDao2();
    }

    @Bean
    public CopyUtil copyUtil() {
        return new CopyUtil();
    }

    @Bean
    public ReportValidator reportValidator() {
        ReportValidator validator = new ReportValidator();
        validator.setService(myService());      
        return validator;
    }

    @Bean 
    public XMLValidator xmlValidator() {
        XMLValidator validator = new XMLValidator();
        validator.setService(myService());
        return validator;
    }
}

Actually, Spring is smart when wiring beans and should only call the myService() function once , and then pass the result to the other myService() calls, resulting in only one bean of MyService .

Make sure you really are getting 2 instances of MyService , eg by adding a log in the constructor of the MyService class.

If you truly see more than one constructor log statement, make sure that you are not declaring other MyService beans in other @Configuration classes, or that you are not using any component annotation on the MyService class (ie don't use @Service , @Component , @Repository ).

If you declare the class with @Service , it effectively instantiates the class and adds it to the context. When you declare it again with @Bean you end up with 2 instances , so don't mix them.


Also, you don't need to use those @Autowired annotations here, or even calls to other beans, because the following will also work:

@Configuration
public class DbConfiguration {

    @Bean
    public MovieDao dao() {
        return new MovieDao();
    }

    @Bean
    public MovieService service(MovieDao dao) {
        return new MovieService(dao);
    }

}

Spring will see that you need a MovieDao to build a MovieService and it will instantiate the dao first and pass it to the service bean. You don't even need to add @Service or similar annotations to your classes!

It really is that good, hope these tips help ;)

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