【问题标题】:Order of Bean Creation WebMvcConfigurerAdapter SpringBean 创建顺序 WebMvcConfigurerAdapter Spring
【发布时间】:2016-08-19 07:12:28
【问题描述】:

我已经在 Spring MVC 中使用以下代码将 xml 转换为 Java 类。谁能告诉我如何设置 bean 创建的顺序。当我运行以下代码时。 JDBCTemplate bean 在 DataSource Bean 之前创建并给出异常,因为 Datasource 为空。

package com.outbottle.config;  

import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.ComponentScan;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;  
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.JstlView;  
import org.springframework.web.servlet.view.UrlBasedViewResolver;  
import org.apache.tomcat.jdbc.pool.DataSource;

@Configuration
@ComponentScan("com.outbottle")
@EnableWebMvc   
public class Config extends WebMvcConfigurerAdapter 
{  
    org.apache.tomcat.jdbc.pool.DataSource dataSource;
    JdbcTemplate jdbcTemplate;

    @Bean  
    public UrlBasedViewResolver setupViewResolver() {  
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();  
        resolver.setPrefix("/WEB-INF/jsp/");  
        resolver.setSuffix(".jsp");  
        resolver.setViewClass(JstlView.class);  
        return resolver;  
    } 

    @Bean  
    public org.apache.tomcat.jdbc.pool.DataSource setDataSource() 
    {  
        dataSource = new DataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUsername("muhiuddin");
        dataSource.setPassword("muhiuddin");
        dataSource.setUrl("jdbc:oracle:thin:@172.19.0.10:1521:db10g");
        dataSource.setMaxIdle(5);
        dataSource.setInitialSize(5);
        return dataSource;
    }

    @Bean  
    public JdbcTemplate setJdbcTemplate() 
    {  
        jdbcTemplate= new JdbcTemplate();
        // setDataSource(); // if I call this function then every thing is OK.
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }      

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
    {
        registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/*");
    }
} 

【问题讨论】:

    标签: java spring spring-mvc


    【解决方案1】:

    TL;DR:永远不要使用实例变量

    你的代码应该是:

    @Bean  
    public javax.sql.DataSource dataSource() 
    {  
        final DataSource dataSource = new DataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUsername("muhiuddin");
        dataSource.setPassword("muhiuddin");
        dataSource.setUrl("jdbc:oracle:thin:@172.19.0.10:1521:db10g");
        dataSource.setMaxIdle(5);
        dataSource.setInitialSize(5);
        return dataSource;
    }
    
    @Bean  
    public JdbcTemplate jdbcTemplate(final javax.sql.DataSource dataSource) 
    {  
        final JdbcTemplate jdbcTemplate= new JdbcTemplate();
        // setDataSource(); // if I call this function then every thing is OK.
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }      
    

    这样,Spring 知道要创建一个JdbcTemplate bean,它需要一个DataSource bean;所以它会正确地决定顺序。

    你使用实例变量绕过了Spring,Spring无法确定其创建时间。


    另外两件事:

    1. @Bean 方法的名称设置 bean 名称,你真的想要一个名为 setDataSourceDataSource bean 吗?
    2. 您的 bean 应该返回 interfaceabstract class 而不是特定类型,这是为了鼓励 interface 自动装配。

    【讨论】:

    • 感谢您的回复。你能解释一下“TL;DR:从不使用实例变量”是什么意思吗?提前致谢。
    • TL:DR;永远不要使用实例变量。 @MUHIUDDIN
    【解决方案2】:

    你可以使用@DependsOn注解来设置bean创建的顺序

    类似的东西:

    @Bean
    @DependsOn("setDataSource")  
    public JdbcTemplate setJdbcTemplate() 
    {  
        jdbcTemplate= new JdbcTemplate();
        // setDataSource(); // if I call this function then every thing is OK.
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }      
    

    但你也可以调用方法本身:

    @Bean  
    public org.apache.tomcat.jdbc.pool.DataSource getDataSource() 
    {  
        DataSource dataSource = new DataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUsername("muhiuddin");
        dataSource.setPassword("muhiuddin");
        dataSource.setUrl("jdbc:oracle:thin:@172.19.0.10:1521:db10g");
        dataSource.setMaxIdle(5);
        dataSource.setInitialSize(5);
        return dataSource;
    }
    
    @Bean  
    public JdbcTemplate setJdbcTemplate() 
    {  
        jdbcTemplate= new JdbcTemplate();
        // setDataSource(); // if I call this function then every thing is OK.
        jdbcTemplate.setDataSource(getDataSource());
        return jdbcTemplate;
    }      
    

    【讨论】:

    • 这是一种绕过@Configuration 滥用的技巧。看我的回答。
    猜你喜欢
    • 2018-06-26
    • 2019-12-25
    • 2019-04-03
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    相关资源
    最近更新 更多