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就好。有更好的方法的 欢迎交流~~

发布了26 篇原创文章 · 获赞 68 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/qq_32193151/article/details/78466152