您的位置:首页 > Web前端 > JavaScript

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

2017-11-07 11:28 519 查看
最近几个月,加班较多。。好久不写了,重新踏上学习探索的道路。这篇文章主要是对前一篇的方案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就好。有更好的方法的 欢迎交流~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐