================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);
}
}
有更好方案的小伙伴欢迎探讨~~