web项目运行时(如JSON parse)手动注入@Autowired等注解的属性值-1
2017-07-27 16:04
465 查看
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 :
TestBean :
(3)方案3:
最终 我们采用了方案3,因为维护起来比较方便
Utils:简易版
Utils:增加本地缓存版
TestBean :
有更好方案的小伙伴欢迎探讨~~
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); } }
有更好方案的小伙伴欢迎探讨~~
相关文章推荐
- web项目运行时(如JSON parse)手动注入@Autowired等注解的属性值-2
- @webservice 注解的类中使用@Autowired 进行bean注入,注入的bean调用时为空的问题
- ssm项目中 @Autowired 注解在接口类上却是注入的是他的实现类
- 【JavaWeb】Spring无法@Autowired注入
- Spring AOP注解通过@Autowired,@Resource,@Qualifier,@PostConstruct,@PreDestroy注入属性的配置文件详解
- Spring @Resource、@Autowired、@Qualifier的注解注入及区别
- @Qualifier注解缩小@Autowired自动注入的范围【Spring 入门】
- spring下应用@Resource, @Autowired 和 @Inject注解进行依赖注入的差
- Spring @Resource、@Autowired、@Qualifier的注解注入及区别
- @Resource、@Autowired、@Qualifier的注解注入及区别
- Spring系列【04】应用@Autowired注解实现Bean的注入
- Spring 注解通过@Autowired,@Resource,@Qualifier,@PostConstruct,@PreDestroy注入属性详解
- Spring AOP注解通过@Autowired,@Resource,@Qualifier,@PostConstruct,@PreDestroy注入属性的配置文件详解
- Spring @Resource、@Autowired、@Qualifier的注解注入及区别
- servlet中利用spring的注解@Autowired自动注入service失败,优雅的解决方法
- Spring @Resource、@Autowired、@Qualifier的注解注入及区别
- Spring @Resource、@Autowired、@Qualifier的注解注入及区别
- Spring @Resource、@Autowired、@Qualifier的注解注入详解
- Spring AOP注解通过@Autowired,@Resource,@Qualifier,@PostConstruct,@PreDestroy注入属性的配置文件详解
- spring boot 中@Autowired注解无法自动注入的错误