spring項目運行時(如new JSON parse等)手動注入@Autowired等註解的屬性值-2

================2019-05-05更新
下面的都是很久之前寫的了,現在看來,有點傻,哈哈哈
其實只需要把你要new的bean 用applicationContext.getAutowireCapableBeanFactory().autowireBean(“your bean”) 就可以了 哈哈哈

最近幾個月,加班較多。。好久不寫了,重新踏上學習探索的道路。這篇文章主要是對前一篇的方案3的一些優化(前一篇地址:http://blog.csdn.net/qq_32193151/article/details/76204394)

1.優化內容
上一篇中的方案3中的getDeclaredFields只能獲取當前類中的所有屬性(包含私有,還有個getFileds只能獲取到包含父類的所有public屬性),但如果我繼承了另一個父類,也想初始化父類中的屬性怎麼辦呢?

2.獲取所有包括父類的屬性

List<Field> fields = new ArrayList<>() ;
Class temp = object.getClass();
/**當父類爲null的時候說明到達了上層是object的類. object類不參與*/
while (temp != null && temp.getSuperclass() != null) {
    fields.addAll(Arrays.asList(temp .getDeclaredFields()));
            /**轉到父類*/
    temp = temp.getSuperclass();
}

3.新增註解類

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by kowalski on 2017/11/7
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotScanAutowired {
}

4.核心工具類

/**
 * Created by Kowalski on 2017/7/27
 * Updated by Kowalski on 2017/7/27
 * 工具類
 */
@Slf4j
public class Utils {

    /**靜態緩存*/
    private static final ConcurrentMap<Class<?>, ConcurrentMap<Field, Object>> map = new ConcurrentHashMap<>();
    /**
     * 初始化bean時(如json parse)注入Service屬性
     * 放在構造方法中初始化(ActivityEngineUtils.initServce(this);)
     * @param object
     */
    public static void initServce(Object object) {

        Map<Field, Object> filedsBeansFromMap = map.get(object.getClass());

        if (filedsBeansFromMap != null) {
            /**遍歷Filed與Spring Bean對應關係*/
            for (Map.Entry<Field, Object> filedsBeans : filedsBeansFromMap.entrySet()) {
                try {
                    filedsBeans.getKey().set(object, filedsBeans.getValue());
                } catch (IllegalAccessException e) {
                    log.error("ActivityEngineUtils initServce IllegalAccessException:", e);
                }
            }
            return;
        }
        List<Field> fields = new ArrayList<>() ;
        Class temp = object.getClass();
        /**當父類爲null的時候說明到達了上層是object的類. object類不參與*/
        while (temp != null && temp.getSuperclass() != null) {
            fields.addAll(Arrays.asList(temp .getDeclaredFields()));
            /**轉到父類*/
            temp = temp.getSuperclass();
        }
        /**Filed與Spring Bean對應關係*/
        ConcurrentMap<Field, Object> tofiledsBeansMap = new ConcurrentHashMap<>();
        for (Field field : fields) {
            /**只針對Autowired 與 Resources註解屬性使用*/
            if (field.isAnnotationPresent(NotScanAutowired.class)|| field.isAnnotationPresent(Autowired.class)|| field.isAnnotationPresent(Resources.class)) {
                try {
                    /**設置私有屬性可寫*/
                    field.setAccessible(true);
                    /**拿到Service 放入對象屬性中*/
                    Object bean = SpringContextsUtil.getApplicationContext().getBean(field.getType());
                    /**給屬性賦值*/
                    field.set(object, bean);
                    tofiledsBeansMap.putIfAbsent(field, bean);
                } catch (IllegalAccessException e) {
                    log.error("Utils initServce IllegalAccessException:", e);
                } catch (Exception e) {
                    log.error("Utils initServce set filed failed:", e);
                }
            }
        }
        map.putIfAbsent(object.getClass(), tofiledsBeansMap);
    }
}

5.簡化之前的initService
這個工具類經過改進後,可以發現,不需要每個子類都放一個initService了,只需要在父類放一份就可以了,爲了方便,抽象出一個類,專門用於初始化這些等待注入的變量:

/**
 * Created by kowalski on 2017/11/7
 *
 */
public class SpringNotScanBeanUtils {
    public SpringNotScanBeanUtils(){
        Utils.initServce(this);
    }
}

到此,只要以後有需要在spring掃描期後注入的spring 管理的bean(如JSON parse) 就可以直接繼承這個SpringNotScanBeanUtils就好。有更好的方法的 歡迎交流~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章