web项目运行时(如JSON parse)手动注入@Autowired等注解的属性值-1

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

1.需求:通过JSON parse成具体对象,对象中有@Autowired,@Resource注解的属性如何注入?
Spring Bean管理的Spring注解的@Autowired或者@Resource属性在项目启动时会交由Spring自动注入具体的属性值,如果我不将Bean交由Spring管理,正常情况下@Autowired,@Resource注解也不会起作用,如何在运行时手动注入被加上@Autowired或者@Resource的属性呢?

2.方案探讨
(1)创建一个被Spring管理的bean,bean中有很多@Autowire的属性,在JSON.parseObject后通过BeanUtils.copyProperties()将属性值copy过来
(2)在构造方法中加入通过applicationContext.getBean(“beanName”)获取到Spring Bean给当前注解属性赋值
(3)拿到当前类的所有属性,再拿到用@Autowired或者@Resource注解的属性,再拿到属性的类型通过applicationContext.getBean(beanType)获得到Spring Bean给当前注解属性赋值

3.方案实行
(1)方案1比较简单,略过
(2)方案2:

SpringContextUtil :

/**
 * Created by Kowalski on 2017/7/27
 * Updated by Kowalski on 2017/7/27
 */
public class SpringContextUtil implements ApplicationContextAware{
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }

    public static Object getBean(Class requiredType) throws BeansException {
        return applicationContext.getBean(requiredType);
    }
}

TestBean :

public class TestBean {

    @Autowired
    private TestInterface testInterface;
    
    TestBean() {
       this.testInterface= (TestInterface) SpringContextUtil.getBean("testInterface");
    }
}

(3)方案3:
最终 我们采用了方案3,因为维护起来比较方便

Utils:简易版

/**
 * Created by Kowalski on 2017/7/27
 * Updated by Kowalski on 2017/7/27
 */
@Slf4j
public class Utils {
    public static void initServce(Object object){
	    /**获得所有属性(包括私有不包括父类)*/
        Field[] fields = object.getClass().getDeclaredFields();

        for(Field field:fields){
            if(field.getAnnotation(Autowired.class) != null || field.getAnnotation(Resources.class) != null){
                /**可设置私有属性*/
                field.setAccessible(true);
                /**拿到单例Service 放入对象属性中*/
                try {
                    field.set(object, SpringContextsUtil.getApplicationContext().getBean(field.getType()));
                }catch (IllegalAccessException e){
                    log.error("Utils initServce IllegalAccessException:{}", e);
                }catch (Exception e){
                    log.error("Utils initServce set filed:{} failed:{}", field.getType(), e);
                }
            }
        }
    }
}

Utils:增加本地缓存版

/**
 * 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<Class<?>, ConcurrentMap<Field, Object>>();
    /**
     * 初始化bean时(如json parse)注入Service属性
     * 放在构造方法中初始化(Utils.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("Utils initServce IllegalAccessException:{}", e);
                }
            }
            return;
        }
        /**获得所有属性(包括私有不包括父类)*/
        Field[] fields = object.getClass().getDeclaredFields();
        /**Filed与Spring Bean对应关系*/
        ConcurrentMap<Field, Object> tofiledsBeansMap = new ConcurrentHashMap<Field, Object>();
        for (Field field : fields) {
            /**只针对Autowired 与 Resources注解属性使用*/
            if (field.getAnnotation(Autowired.class) != null || field.getAnnotation(Resources.class) != null) {
                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);
    }
}

TestBean :

public class TestBean {

    @Autowired
    private TestInterface testInterface;
    
    TestBean() {
       Utils.initServce(this);
    }
}

有更好方案的小伙伴欢迎探讨~~

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

猜你喜欢

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