java - 使用不受 Spring 管理的静态方法初始化类

标签 java spring spring-boot

我有一个名为 ConfigManagement 的类,它仅使用静态方法/字段。其中一个名为initializeConfig() 的静态方法采用Property 对象(指向application.properties)作为输入并填充字段,并使用application.properties 文件中的值调用一些其他方法。

public class ConfigManagement {

   private static String signatureAlgorithm;
   private static String myName;
   private static RSAPublicKey myPublicKey;
   private static RSAPrivateKey myPrivateKey;
   private static HashMap<String, RSAPublicKey> peerPubKeys = new HashMap<String, RSAPublicKey>();
   private static boolean isInitialized = false;
/**
 * @return the signatureAlgorithm
 */

public static void initializeConfig(Properties props)  {
    signatureAlgorithm = props.getProperty("cybertrust.crypto.signatureAlgorithm");
    myName = props.getProperty("cybertrust.crypto.myName");
    try {
        try {
            myPublicKey = Loader.getPublicKeyFromCertificateFile(props.getProperty("cybertrust.crypto.myCertificate"));
        }
        catch (Exception e) {
            throw new IllegalStateException("cybertrust.crypto.myCertificate is empty, the file is not found or it contains invalid data");
        }
        try {
            myPrivateKey = Loader.getPrivateKeyFromFile(props.getProperty("cybertrust.crypto.myPrivateKey"));
        }
        catch (Exception e) {
            throw new IllegalStateException("cybertrust.crypto.myPrivateKey is empty, the file is not found or it contains invalid data");
        }
        peerPubKeys.put(myName, myPublicKey);
        int peerCounter = 0;
        do {
            String peerNameProp = String.format("cybertrust.crypto.peerModules.%d.name", peerCounter);
            String peerName = props.getProperty(peerNameProp);
            if (peerName == null)
                break;
            String peerNameCertFileProp = String.format("cybertrust.crypto.peerModules.%d.certificate", peerCounter);
            String peerNameCertFile = props.getProperty(peerNameCertFileProp);
            if (peerNameCertFile == null) // Do not halt the program, produce though an error
                Logger.getLogger("ConfigManagement").log(Level.SEVERE, 
                        String.format("Property %s not found while property %s is defined", peerNameCertFile, peerNameProp));
                // instantiate public key from file
                try {
                    RSAPublicKey peerRsaPubKey = Loader.getPublicKeyFromCertificateFile(peerNameCertFile); 
                    peerPubKeys.put(peerName, peerRsaPubKey);
                }
                catch (Exception e) {
                    Logger.getLogger("ConfigManagement").log(Level.SEVERE, 
                            String.format("File %s specified in property %s not found or does not contains a valid RSA key", peerNameCertFile, peerNameCertFileProp));              }
                peerCounter++;
        } while (true);
    }
    catch (Exception e) {
        throw(e);
    }
    if ((myPublicKey == null) || (signatureAlgorithm == null) || (myName == null))
        throw new IllegalStateException("one of the properties cybertrust.crypto.signatureAlgorithm, cybertrust.crypto.myName, cybertrust.crypto.myPublicKey, cybertrust.crypto.myPrivateKey is not defined");  
    isInitialized = true;
}

private static void testInitialized() {
    if (!isInitialized)
        throw new IllegalStateException("The configuration has not been initialized");
}

public static String getSignatureAlgorithm() {
    testInitialized();
    return signatureAlgorithm;
}
/**
 * @return the myName
 */
public static String getMyName() {
    testInitialized();
    return myName;
}
/**
 * @return the myPublicKey
 */
public static RSAPublicKey getMyPublicKey() {
    testInitialized();
    return myPublicKey;
}
/**
 * @return the myPrivateKey
 */
public static RSAPrivateKey getMyPrivateKey() {
    testInitialized();
    return myPrivateKey;
}

public static RSAPublicKey getPublicKey(String peerName) throws NoSuchElementException {
    testInitialized();
    RSAPublicKey result = peerPubKeys.get(peerName);
    if (result == null)
        throw new NoSuchElementException("No known key for module " + peerName);
    else
        return result;
}
}

application.properties 文件看起来像这样:

cybertrust.crypto.myName=tms1235.cybertrust.eu
cybertrust.crypto.myCertificate=tms1235.cert.pem
cybertrust.crypto.myPrivateKey=tms1235.key.pem

cybertrust.crypto.signatureAlgorithm=SHA256withRSA

cybertrust.crypto.peerModules.0.name=sga1234.cybertrust.eu
cybertrust.crypto.peerModules.0.certificate=sga1234.cert.pem

cybertrust.crypto.peerModules.1.name=tms1234.cybertrust.eu
cybertrust.crypto.peerModules.1.certificate=tms1234.cert.pem

在一个简单的 Java 项目中,我运行 ConfigManagement.initializeConfig(props);在 main() 中,字段已初始化,我可以使用其余的方法。到了 Spring ,事情就没那么简单了。 我正在尝试将此代码集成到 SpringBoot 应用程序中,但我不知道如何/在哪里初始化此类。 我把Spring配置贴出来供引用:

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.cybertrust.tms")
//@PropertySource({ "classpath:persistence-mysql.properties" })
@PropertySource({ "classpath:model.properties" })
public class DemoAppConfig implements WebMvcConfigurer {

    @Autowired
    private Environment env;

    private Logger logger = Logger.getLogger(getClass().getName());

    // define a bean for ViewResolver

    @Bean
    public DataSource myDataSource() {

        // create connection pool
        ComboPooledDataSource myDataSource = new ComboPooledDataSource();

        // set the jdbc driver
        try {
            myDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");        
        }
        catch (PropertyVetoException exc) {
            throw new RuntimeException(exc);
        }

        // for sanity's sake, let's log url and user ... just to make sure we are reading the data
        logger.info("jdbc.url=" + env.getProperty("spring.datasource.url"));
        logger.info("jdbc.user=" + env.getProperty("spring.datasource.username"));

        // set database connection props
        myDataSource.setJdbcUrl(env.getProperty("spring.datasource.url"));
        myDataSource.setUser(env.getProperty("spring.datasource.username"));
        myDataSource.setPassword(env.getProperty("spring.datasource.password"));

        // set connection pool props
        myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
        myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
        myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));     
        myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));

        return myDataSource;
    }

    private Properties getHibernateProperties() {

        // set hibernate properties
        Properties props = new Properties();

        props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
        props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        props.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));

        return props;               
    }


    // need a helper method 
    // read environment property and convert to int

    private int getIntProperty(String propName) {

        String propVal = env.getProperty(propName);

        // now convert to int
        int intPropVal = Integer.parseInt(propVal);

        return intPropVal;
    }   

    @Bean
    public LocalSessionFactoryBean sessionFactory(){

        // create session factorys
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();

        // set the properties
        sessionFactory.setDataSource(myDataSource());
        sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
        sessionFactory.setHibernateProperties(getHibernateProperties());

        return sessionFactory;
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {

        // setup transaction manager based on session factory
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(sessionFactory);

        return txManager;
    }


    @Bean
    public ModelMapper modelMapper() {
        return new ModelMapper();
    }

    @Bean
    public ConfigManagement configManagement() {
        return new ConfigManagement();
    }


}

以及 Spring Boot main():

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.cybertrust.tms")
//@PropertySource({ "classpath:persistence-mysql.properties" })
@PropertySource({ "classpath:model.properties" })
//@EnableAutoConfiguration(exclude = HibernateJpaAutoConfiguration.class)

@SpringBootApplication(exclude = {HibernateJpaAutoConfiguration.class})
public class TMS extends SpringBootServletInitializer {

    public static void main(String[] args) throws Exception {

        SpringApplication.run(TMS.class, args);
    }

}

最佳答案

您的静态解决方案无法在 Spring 环境中正常工作,因为静态可以在 Spring 启动并加载所有 bean 和属性之前执行

您应该通过使用 @Value 获取属性来以 Spring 方式重写代码

Injecting a property with the @Value annotation is straightforward:

@Value( "${jdbc.url}" ) private String jdbcUrl;

关于java - 使用不受 Spring 管理的静态方法初始化类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60990610/

相关文章:

java - 构造函数中模拟 bean 的 NullPointerException - 如何通过首先自定义构造函数来正确模拟模拟 Bean?

java - Spring REST 服务证书身份验证

java - 多个模块,每个模块在 gradle 中使用 spring 提供休息服务

spring - 类路径资源 [application-test.properties] 无法打开,因为它不存在

java - 如何在java中关闭包含框架的单个类

java - CrudRepository 按一对多关系过滤

java - Spring Boot 通过 REST 端点将大型数据库导出到 csv

Java:用于标志检查的按位运算

java - 在 XPath 中,如何选择与子集不匹配的所有节点?

java - 清楚地了解 Java 中的转换和继承