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