自己new的物件怎麼注入spring管理的物件
阿新 • • 發佈:2018-12-23
本文主要參考了以下兩篇部落格,然後將兩者整合起來
正文:
我這裡主要是想在專案中運用裝飾者模式,但是因為自己new出來的裝飾者service (不受spring管理)並沒有注入其他service時,但是我又確實需要去注入,這個時候就找到這兩個部落格,結合起來。
使用方法:裝飾者service需要繼承這個類,然後裝飾者service正常new的時候,裝飾者service中註解了@Autowired的屬性就會在spring容器中找到並注入。
理解:initNewService因為是被spring容器管理的,且實現了ApplicationContextAware(或者ServletContextAware ),所以在spring容器初始化的時候回注入ApplicationContextAware,我們把它儲存在類中,並設定為static,因此每個繼承此類的物件都能拿到ApplicationContextAware。然後繼承類初始化的時候,我們通過屬性的型別到容器中找到對應的物件,並通過反射注入進來。
程式碼如下:
@Service public class InitNewService implements ApplicationContextAware { private static Logger logger = LoggerFactory.getLogger(InitNewService.class); private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * 將繼承此類的service中的欄位(註解了@Autowired 或者@Resource)等注入進來 */ public InitNewService(){ if (this.applicationContext == null){ return; } if (this.getClass().isAnnotationPresent(org.springframework.stereotype.Service.class) || this.getClass().isAnnotationPresent(org.springframework.stereotype.Controller.class) || this.getClass().isAnnotationPresent(org.springframework.stereotype.Component.class) ){ return; } Class clazz = this.getClass(); do { Field[] fields = clazz.getDeclaredFields(); for (Field f : fields) { if (f.isAnnotationPresent(org.springframework.beans.factory.annotation.Autowired.class) || f.isAnnotationPresent(javax.annotation.Resource.class)){ try { String simpleName = f.getType().getSimpleName(); String beanName = StrUtils.toLowerCaseFirstOne(simpleName); Object bean = applicationContext.getBean(beanName); if (bean == null){ return; } boolean accessible = f.isAccessible(); f.setAccessible(true); f.set(this,bean); f.setAccessible(accessible); }catch (Exception e){ logger.error(clazz.getName() + "當new物件注入類" + f.getName() + "的時候,發生了錯誤",e); e.printStackTrace(); } } } clazz = clazz.getSuperclass(); } while (clazz != Object.class); } }