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

我的需求:

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

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

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

*.properties中的值,怎么办?

我项目的大概情况:

  web.xml

<context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:/spring/spring-context.xmlparam-value>
    context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    listener>

    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListenerlistener-class>
    listener>
    <servlet>
        <servlet-name>mvc-dispatcherservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:/spring/spring-mvc.xmlparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>mvc-dispatcherservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

 

  spring-context.xml

<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*:config.propertiesvalue>
            <value>classpath*:jdbc.propertiesvalue>
            <value>classpath*:log4j.propertiesvalue>
        list>
    property>
bean>

准备代码:

1、写一个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);
    }

}

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

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 implements FetchService {

    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 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 class

所以在debug的过程中这个被@PostConstruct注解的init()方法在Spring容器启动的时候会运行8次,但是4个class是能通过

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

(肯定有更好的方法但是我没有发现,希望大家可以告诉我)

 

你可能感兴趣的:(Spring中抽象类中使用EmbeddedValueResolverAware和@PostConstruct获取配置文件中的参数值)