Spring 3.1配置:环境未注入

发布于 2024-12-14 17:10:30 字数 7381 浏览 0 评论 0 原文

我在 spring 3.1 配置中使用以下内容:

@Configuration
@EnableTransactionManagement
public class DataConfig {
    @Inject
    private Environment env;
    @Inject
    private DataSource dataSource;

    // @Bean
    public SpringLiquibase liquibase() {
        SpringLiquibase b = new SpringLiquibase();
        b.setDataSource(dataSource);
        b.setChangeLog("classpath:META-INF/db-changelog-master.xml");
        b.setContexts("test, production");
        return b;
    }

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean b = new LocalContainerEntityManagerFactoryBean();
        b.setDataSource(dataSource);
        HibernateJpaVendorAdapter h = new HibernateJpaVendorAdapter();
        h.setShowSql(env.getProperty("jpa.showSql", Boolean.class));
        h.setDatabasePlatform(env.getProperty("jpa.database"));

        b.setJpaVendorAdapter(h);
        return (EntityManagerFactory) b;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
        PersistenceExceptionTranslationPostProcessor b = new PersistenceExceptionTranslationPostProcessor();
        // b.setRepositoryAnnotationType(Service.class);
        // do this to make the persistence bean post processor pick up our @Service class. Normally
        // it only picks up @Repository
        return b;

    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager b = new JpaTransactionManager();
        b.setEntityManagerFactory(entityManagerFactory());
        return b;
    }

    /**
     * Allows repositories to access RDBMS data using the JDBC API.
     */
    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource);
    }


    @Bean(destroyMethod = "close")
    public DataSource dataSource() {

        BasicDataSource db = new BasicDataSource();
        if (env != null) {
            db.setDriverClassName(env.getProperty("jdbc.driverClassName"));
            db.setUsername(env.getProperty("jdbc.username"));
            db.setPassword(env.getProperty("jdbc.password"));
        } else {
            throw new RuntimeException("environment not injected");
        }
        return db;
    }
}

问题是变量 env 未注入并且始终为 null。

我没有对环境设置进行任何操作,因为我不知道是否需要或如何设置。我查看了温室示例,但没有找到任何专门针对环境的内容。我应该怎么做才能确保注入 env

相关文件:

// CoreConfig.java
@Configuration
public class CoreConfig {

    @Bean
    LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

    /**
     * Properties to support the 'standard' mode of operation.
     */
    @Configuration
    @Profile("standard")
    @PropertySource("classpath:META-INF/runtime.properties")
    static class Standard {
    }

}


// the Webconfig.java
@Configuration
@EnableWebMvc
@EnableAsync
// @EnableScheduling
@EnableLoadTimeWeaving
@ComponentScan(basePackages = "com.jfd", excludeFilters = { @Filter(Configuration.class) })
@Import({ CoreConfig.class, DataConfig.class, SecurityConfig.class })
@ImportResource({ "/WEB-INF/spring/applicationContext.xml" })
public class WebConfig extends WebMvcConfigurerAdapter {


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/images/**").addResourceLocations(
                "/images/");
    }

    @Bean
    public BeanNameViewResolver beanNameViewResolver() {
        BeanNameViewResolver b = new BeanNameViewResolver();
        b.setOrder(1);
        return b;
    }

    @Bean
    public InternalResourceViewResolver internalResourceViewResolver() {
        InternalResourceViewResolver b = new InternalResourceViewResolver();
        b.setSuffix(".jsp");
        b.setPrefix("/WEB-INF/jsp/");
        b.setOrder(2);
        return b;
    }

    @Bean
    public CookieLocaleResolver localeResolver() {
        CookieLocaleResolver b = new CookieLocaleResolver();
        b.setCookieMaxAge(100000);
        b.setCookieName("cl");
        return b;
    }

    // for messages
    @Bean
    public ResourceBundleMessageSource messageSource() {
        ResourceBundleMessageSource b = new ResourceBundleMessageSource();
        b.setBasenames(new String[] { "com/jfd/core/CoreMessageResources",
                "com/jfd/common/CommonMessageResources",
                "com/jfd/app/AppMessageResources",
                "com/jfd/app/HelpMessageResources" });
        b.setUseCodeAsDefaultMessage(false);
        return b;
    }

    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();

        Properties mappings = new Properties();
        mappings.put("org.springframework.web.servlet.PageNotFound", "p404");
        mappings.put("org.springframework.dao.DataAccessException",
                "dataAccessFailure");
        mappings.put("org.springframework.transaction.TransactionException",
                "dataAccessFailure");
        b.setExceptionMappings(mappings);
        return b;
    }

    /**
     * ViewResolver configuration required to work with Tiles2-based views.
     */
    @Bean
    public ViewResolver viewResolver() {
        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
        viewResolver.setViewClass(TilesView.class);
        return viewResolver;
    }

    /**
     * Supports FileUploads.
     */
    @Bean
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(500000);
        return multipartResolver;
    }

    // for configuration
    @Bean
    public CompositeConfigurationFactoryBean myconfigurations()
            throws ConfigurationException {
        CompositeConfigurationFactoryBean b = new CompositeConfigurationFactoryBean();
        PropertiesConfiguration p = new PropertiesConfiguration(
                "classpath:META-INF/app-config.properties");
        p.setReloadingStrategy(new FileChangedReloadingStrategy());

        b.setConfigurations(new org.apache.commons.configuration.Configuration[] { p });
        b.setLocations(new ClassPathResource[] { new ClassPathResource(
                "META-INF/default-config.properties") });
        return b;
    }

    @Bean
    org.apache.commons.configuration.Configuration configuration()
            throws ConfigurationException {
        return myconfigurations().getConfiguration();
    }


// and the SecurityConfig.java
@Configuration
@ImportResource({ "/WEB-INF/spring/applicationContext-security.xml" })
public class SecurityConfig {

    @Bean
    public BouncyCastleProvider bcProvider() {
        return new BouncyCastleProvider();
    }

    @Bean
    public PasswordEncryptor jasyptPasswordEncryptor() {

        ConfigurablePasswordEncryptor b = new ConfigurablePasswordEncryptor();
        b.setAlgorithm("xxxxxx");
        return b;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        PasswordEncoder b = new org.jasypt.spring.security3.PasswordEncoder();
        b.setPasswordEncryptor(jasyptPasswordEncryptor());
        return b;
    }

}

在applicationcontext.xml中,它只导入了两个xml来配置缓存和cassandra,所以它可能并不重要。

I am using the following for the spring 3.1 configuration:

@Configuration
@EnableTransactionManagement
public class DataConfig {
    @Inject
    private Environment env;
    @Inject
    private DataSource dataSource;

    // @Bean
    public SpringLiquibase liquibase() {
        SpringLiquibase b = new SpringLiquibase();
        b.setDataSource(dataSource);
        b.setChangeLog("classpath:META-INF/db-changelog-master.xml");
        b.setContexts("test, production");
        return b;
    }

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean b = new LocalContainerEntityManagerFactoryBean();
        b.setDataSource(dataSource);
        HibernateJpaVendorAdapter h = new HibernateJpaVendorAdapter();
        h.setShowSql(env.getProperty("jpa.showSql", Boolean.class));
        h.setDatabasePlatform(env.getProperty("jpa.database"));

        b.setJpaVendorAdapter(h);
        return (EntityManagerFactory) b;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
        PersistenceExceptionTranslationPostProcessor b = new PersistenceExceptionTranslationPostProcessor();
        // b.setRepositoryAnnotationType(Service.class);
        // do this to make the persistence bean post processor pick up our @Service class. Normally
        // it only picks up @Repository
        return b;

    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager b = new JpaTransactionManager();
        b.setEntityManagerFactory(entityManagerFactory());
        return b;
    }

    /**
     * Allows repositories to access RDBMS data using the JDBC API.
     */
    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource);
    }


    @Bean(destroyMethod = "close")
    public DataSource dataSource() {

        BasicDataSource db = new BasicDataSource();
        if (env != null) {
            db.setDriverClassName(env.getProperty("jdbc.driverClassName"));
            db.setUsername(env.getProperty("jdbc.username"));
            db.setPassword(env.getProperty("jdbc.password"));
        } else {
            throw new RuntimeException("environment not injected");
        }
        return db;
    }
}

the issue is that the variable env is not injected and is always null.

I have not done anything about the Environment setup since I do not know if it's needed or how to. I looked at the greenhouse example and i did not find anything specifically for Environment. What should I do to make sure the env is injected?

The related files:

// CoreConfig.java
@Configuration
public class CoreConfig {

    @Bean
    LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

    /**
     * Properties to support the 'standard' mode of operation.
     */
    @Configuration
    @Profile("standard")
    @PropertySource("classpath:META-INF/runtime.properties")
    static class Standard {
    }

}


// the Webconfig.java
@Configuration
@EnableWebMvc
@EnableAsync
// @EnableScheduling
@EnableLoadTimeWeaving
@ComponentScan(basePackages = "com.jfd", excludeFilters = { @Filter(Configuration.class) })
@Import({ CoreConfig.class, DataConfig.class, SecurityConfig.class })
@ImportResource({ "/WEB-INF/spring/applicationContext.xml" })
public class WebConfig extends WebMvcConfigurerAdapter {


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/images/**").addResourceLocations(
                "/images/");
    }

    @Bean
    public BeanNameViewResolver beanNameViewResolver() {
        BeanNameViewResolver b = new BeanNameViewResolver();
        b.setOrder(1);
        return b;
    }

    @Bean
    public InternalResourceViewResolver internalResourceViewResolver() {
        InternalResourceViewResolver b = new InternalResourceViewResolver();
        b.setSuffix(".jsp");
        b.setPrefix("/WEB-INF/jsp/");
        b.setOrder(2);
        return b;
    }

    @Bean
    public CookieLocaleResolver localeResolver() {
        CookieLocaleResolver b = new CookieLocaleResolver();
        b.setCookieMaxAge(100000);
        b.setCookieName("cl");
        return b;
    }

    // for messages
    @Bean
    public ResourceBundleMessageSource messageSource() {
        ResourceBundleMessageSource b = new ResourceBundleMessageSource();
        b.setBasenames(new String[] { "com/jfd/core/CoreMessageResources",
                "com/jfd/common/CommonMessageResources",
                "com/jfd/app/AppMessageResources",
                "com/jfd/app/HelpMessageResources" });
        b.setUseCodeAsDefaultMessage(false);
        return b;
    }

    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();

        Properties mappings = new Properties();
        mappings.put("org.springframework.web.servlet.PageNotFound", "p404");
        mappings.put("org.springframework.dao.DataAccessException",
                "dataAccessFailure");
        mappings.put("org.springframework.transaction.TransactionException",
                "dataAccessFailure");
        b.setExceptionMappings(mappings);
        return b;
    }

    /**
     * ViewResolver configuration required to work with Tiles2-based views.
     */
    @Bean
    public ViewResolver viewResolver() {
        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
        viewResolver.setViewClass(TilesView.class);
        return viewResolver;
    }

    /**
     * Supports FileUploads.
     */
    @Bean
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(500000);
        return multipartResolver;
    }

    // for configuration
    @Bean
    public CompositeConfigurationFactoryBean myconfigurations()
            throws ConfigurationException {
        CompositeConfigurationFactoryBean b = new CompositeConfigurationFactoryBean();
        PropertiesConfiguration p = new PropertiesConfiguration(
                "classpath:META-INF/app-config.properties");
        p.setReloadingStrategy(new FileChangedReloadingStrategy());

        b.setConfigurations(new org.apache.commons.configuration.Configuration[] { p });
        b.setLocations(new ClassPathResource[] { new ClassPathResource(
                "META-INF/default-config.properties") });
        return b;
    }

    @Bean
    org.apache.commons.configuration.Configuration configuration()
            throws ConfigurationException {
        return myconfigurations().getConfiguration();
    }


// and the SecurityConfig.java
@Configuration
@ImportResource({ "/WEB-INF/spring/applicationContext-security.xml" })
public class SecurityConfig {

    @Bean
    public BouncyCastleProvider bcProvider() {
        return new BouncyCastleProvider();
    }

    @Bean
    public PasswordEncryptor jasyptPasswordEncryptor() {

        ConfigurablePasswordEncryptor b = new ConfigurablePasswordEncryptor();
        b.setAlgorithm("xxxxxx");
        return b;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        PasswordEncoder b = new org.jasypt.spring.security3.PasswordEncoder();
        b.setPasswordEncryptor(jasyptPasswordEncryptor());
        return b;
    }

}

in the applicationcontext.xml, it only imported two xmls to config cache and cassandra, so it may not be important.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

溺孤伤于心 2024-12-21 17:10:37

我在 spring-social-sample 应用程序中也遇到了类似的问题。

在我将字段级别 @Inject 转换为构造函数级别注入后,它起作用了。

I also had the similar issue with spring-social-sample app.

After I converted field level @Inject to constructor level inject it worked.

鞋纸虽美,但不合脚ㄋ〞 2024-12-21 17:10:36

@jfd,

我没有立即发现您的配置有任何问题,会导致注入环境失败。

如果您从头开始使用一个空的 @Configuration 类,然后 @Inject 环境,它对您有用吗?

如果是,那么它在什么时候开始失败?

您愿意将示例减少到可能失败的最小配置并将其作为复制项目提交吗?这里的说明使这尽可能简单: https://github.com/SpringSource/spring -framework-issues#readme

谢谢!

@jfd,

I don't immediately see anything wrong with your configuration that would cause a failure to inject the Environment.

If you start from scratch with an empty @Configuration class, and then @Inject the Environment, does it work for you?

If yes, then at what point does it begin to fail?

Would you be willing to reduce the example down to the smallest possible configuration that fails and submit it as a reproduction project? The instructions here make this as simple as possible: https://github.com/SpringSource/spring-framework-issues#readme

Thanks!

仙女 2024-12-21 17:10:36

我在我的项目中检测到类似的错误,如上所述 此处
我还发现,需要调用 afterproperties 才能获取 sessionFactory。
...是的,我也在使用 Spring Security(这可能是问题的根源)。

我的 @Configuration 带注释的类对包含基于 Hibernate 的 DAO 的包使用 @ComponentScan,并使用 @Bean 带注释的方法来创建 DAO 使用的 SessionFactory。在运行时,抛出异常,提到未找到“sessionFactory”或“hibernateTemplate”。看起来 DAO 是在创建 SessionFactory 之前构建的。对我来说,一种解决方法是将组件扫描指令放回 XML 文件 () 中,并将 @ComponentScan 替换为该文件的 @ImportResource。

@Configuration
//@ComponentScan(basePackages = "de.webapp.daocustomer", excludeFilters = {@ComponentScan.Filter(Configuration.class), @ComponentScan.Filter(Controller.class)})
@ImportResource({"classpath*:componentScan.xml","classpath*:properties-config.xml","classpath*:security-context.xml"})
public class AppConfig
{
...
@Bean
public SessionFactory sessionFactory() throws Exception
{
    AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
    bean.setDataSource(dataSource());
    bean.setPackagesToScan(new String[] {"de.webapp"});
    bean.setHibernateProperties(hibernateProps());
    bean.afterPropertiesSet();
    return bean.getObject();
}

另外有趣的事实是:如果包含 @ComponentScan,则永远不会到达方法 sessionFactory() 中设置的断点!

I've detect a similar error for my project as mentioned here.
I've also figure out, that a call of afterproperties is necessary to get the sessionFactory.
... and yes, I'm using Spring Security too (which may be the source of the problem).

My @Configuration annotated class uses @ComponentScan for packages containing Hibernate based DAOs and a @Bean annotated method for creating the SessionFactory used by the DAOs. At runtime, a exception is thrown, mentioned that 'sessionFactory' or 'hibernateTemplate' was not found. It seems that the DAOs are constructed before the SessionFactory was created. One workaround for me was to put the component scan directive back in a XML file () and replace @ComponentScan with @ImportResource of that file.

@Configuration
//@ComponentScan(basePackages = "de.webapp.daocustomer", excludeFilters = {@ComponentScan.Filter(Configuration.class), @ComponentScan.Filter(Controller.class)})
@ImportResource({"classpath*:componentScan.xml","classpath*:properties-config.xml","classpath*:security-context.xml"})
public class AppConfig
{
...
@Bean
public SessionFactory sessionFactory() throws Exception
{
    AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
    bean.setDataSource(dataSource());
    bean.setPackagesToScan(new String[] {"de.webapp"});
    bean.setHibernateProperties(hibernateProps());
    bean.afterPropertiesSet();
    return bean.getObject();
}

Also interesting fact: if @ComponentScan is included, a breakpoint set in method sessionFactory() was never reached !

帝王念 2024-12-21 17:10:34

问题在于 spring security 的“记住我”功能。如果我采取这一行 ; > 输出。一切正常。如果出现此行,它将尝试在执行其他操作之前加载数据库,并且 env 从未被注入。

The problem is with the spring security for the remember me feature. if I take this line <code> <remember-me data-source-ref="dataSource" /> </code> out. everything works fine. if this line presents, it will try to load the db before anything else and env was never injected.

眉目亦如画i 2024-12-21 17:10:34

如果您不使用完整的 Java EE 兼容服务器,则必须将 javax.inject.jar 包含到项目类路径中以添加对 @Inject 的支持。你也可以尝试使用spring原生的@Autowired注解。

If you don't use full Java EE compatible server you have to include javax.inject.jar to your project classpath to add the support of @Inject. You can also try to use spring's native @Autowired annotation.

抱猫软卧 2024-12-21 17:10:33

不知道为什么,但使用 @Resource 注释有效为我。 @Autowired 总是返回 null。

Not sure why, but using the @Resource annotation worked for me. @Autowired always returned null.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文