Spring中抽象類中使用EmbeddedValueResolverAware和@PostConstruct獲取配置文件中的參數值


我的需求:

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

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

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

*.properties中的值,怎么辦?

我項目的大概情況:

  web.xml

<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.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*:*.properties</value>--> <--這樣也可以,只是感覺不是很明了-->
            <value>classpath*:config.properties</value>
            <value>classpath*:jdbc.properties</value>
            <value>classpath*:log4j.properties</value>
        </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<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 class

所以在debug的過程中這個被@PostConstruct注解的init()方法在Spring容器啟動的時候會運行8次,但是4個class是能通過

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

(肯定有更好的方法但是我沒有發現,希望大家可以告訴我)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM