Spring中抽象类中使用EmbeddedValueResolverAware和@PostConstruct获取配置文件中的参数值

个人需求:

  我有一个 abstract class 中包含了不少子类中须要用到的公共方法和变量,我想在抽象类中java

使用@Value获取*.properties中的值。可是@Value必需要在Spring的Bean生命周期管理下才能web

使用,好比类被@Controller、@Service、@Component等注解标注。那我就想在抽象类中获取spring

*.properties中的值,怎么办?spring-mvc

我项目的大概状况:mvc

  web.xmlapp

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/spring/spring-context.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/spring/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

 

  spring-context.xmlide

<context:component-scan base-package="com.hyxf.amlfetch" />

<context:annotation-config />

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreResourceNotFound" value="true" />
    <property name="locations">
        <list>
            <!--<value>classpath*:*.properties</value>--> <--这样也能够,只是感受不是很明了-->
            <value>classpath*:config.properties</value>
            <value>classpath*:jdbc.properties</value>
            <value>classpath*:log4j.properties</value>
        </list>
    </property>
</bean>

准备代码:

一、写一个PropertiesUtil工具类,实现EmbeddedValueResolverAware 工具

package com.hyxf.amlfetch.common.util;

import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;

/**
 * 获取properties文件中的value的工具类
 */
@Component
public class PropertiesUtil implements EmbeddedValueResolverAware {
    private StringValueResolver stringValueResolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        stringValueResolver = resolver;
    }
    public String getPropertiesValue(String name){
        return stringValueResolver.resolveStringValue(name);
    }

}

二、在须要获取*.properties值的抽象类中引入PropertiesUtil工具类,并使用@PostConstruct注解进行初始化。oop

package com.hyxf.amlfetch.biz.service.coop;

import com.hyxf.amlfetch.common.util.PropertiesUtil;
import org.springframework.beans.factory.annotation.Autowired;

import com.hyxf.amlfetch.common.util.Logger;
import com.hyxf.amlfetch.dao.mapper.aml.OdsT2aBatchMapper;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

public abstract class AbstractFetchService<T> implements FetchService<T> {

    protected Logger logger = Logger.getLogger(this.getClass());
    
    @Autowired
    protected OdsT2aBatchMapper odsT2aBatchMapper;

    @Autowired private PropertiesUtil propertiesUtil; private static final String DB_READ_NUM_KEY = "each_db_read_num";

    private static final String DB_WRITE_NUM_KEY = "each_db_write_num";

    private static Map<String, String> dbNum = new HashMap<>(); /**
     * 索引位置
     */
    protected static final Integer FROM_INDEX = 0;

    /**
     * 加载配置文件的值
     * 抽象类不可以使用@Value,在spring容器初始话的时候来获取这个值
     */ @PostConstruct public void init() {
        String eachDbWriteNum = propertiesUtil.getPropertiesValue("${" + DB_WRITE_NUM_KEY + "}");
        if(StringUtils.isEmpty(dbNum.get(DB_WRITE_NUM_KEY))) {
            dbNum.put(DB_WRITE_NUM_KEY, eachDbWriteNum);
        }
        String eachDbReadNum = propertiesUtil.getPropertiesValue("${" + DB_READ_NUM_KEY + "}");
        if(StringUtils.isEmpty(dbNum.get(DB_READ_NUM_KEY))) {
            dbNum.put(DB_READ_NUM_KEY, eachDbReadNum);
        }
    }

    public Integer getEachDbWriteNum() {
        if(StringUtils.isEmpty(dbNum.get(DB_WRITE_NUM_KEY))) {
            return 0;
        }
        return Integer.parseInt(dbNum.get(DB_WRITE_NUM_KEY));
    }

    public Integer getEachDbReadNum() {
        if(StringUtils.isEmpty(dbNum.get(DB_READ_NUM_KEY))) {
            return 0;
        }
        return Integer.parseInt(dbNum.get(DB_READ_NUM_KEY));
    }
}

  解释一下,为何这里用了一个static的HashMap,由于这个抽象类有8个子类,其中4个class 和 4个 abstract classfetch

因此在debug的过程当中这个被@PostConstruct注解的init()方法在Spring容器启动的时候会运行8次,可是4个class是能经过

propertiesUtil获取到值的,而4个abstract class 是获取不到值的。因此就把第一次获取到的properties中的值用map存下来。

(确定有更好的方法可是我没有发现,但愿你们能够告诉我)

相关文章
相关标签/搜索