通過反射途徑獲得的物件如何自動注入spring Bean
框架:spring+struts2
spring負責物件管理,MVC;自動裝配由struts2完成 (bean定義+getter/setter方法);
專案中用到了通過反射途徑呼叫相應的業務模組的邏輯。controller接收http請求後,根據請求引數獲得業務程式碼和方法引數,到.xml配置檔案中讀取相應的類名,方法名,引數型別列表,呼叫ReflectASM.jar(高效反射工具)中的
public static Object AsmMethodRefUtil.invokeAsmFunc(
String className, String methodName, Object[] paramValues, Class <?>[] paramTypes);
方法。該工具根據類名生成相應的物件,呼叫方法,傳入引數列表並返回所呼叫的方法返回值。
我的問題是:需要在反射生成的物件中注入一個spring bean定義的物件,然而被注入的容器類本身不是spring bean元件,怎麼辦?
原理理解:
spring自動注入物件是通過建立一個BeanFactory並傳入applicationContext配置檔案物件,然後呼叫BeanFactory的getBean方法來實現相互依賴的物件獲取和裝配的。如果被注入的容器沒有在spring bean中配置,而是通過反射途徑生成,不能獲取BeanFactory,就意味著不能進行自動注入。
如果在元件上實現一些spring提供的介面,如BeanFactoryAware、ApplicationContextAware,就可以手動方式獲取BeanFactory,實現依賴注入。
在兩個網頁找到了共3種方法。
我使用了第一個網頁的第一種方法。
被注入的容器類需要extends BaseAutoAware。因為我的元件已經繼承一個父類,我把其中的程式碼移植到了元件繼承的父類中。
public class BaseWebService
{
public BaseSfqxWebService() {
((AutowireCapableBeanFactory)retrieveBeanFactory())
.autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true );
}
private BeanFactory retrieveBeanFactory() {
BaseLocator bl=new BaseLocator();
BeanFactory f = bl.getFactory();
return f;
}
}
BaseLocator類,實現BeanFactoryAware介面,獲取BeanFactory物件:
(需要spring-beans-XXX.jar)
public class BaseLocator implements BeanFactoryAware {
private static BeanFactory factory = null;
private static BaseLocator baselocator = null;
@Override
public void setBeanFactory(BeanFactory f) throws BeansException {
factory = f;
}
public BeanFactory getFactory(){
return factory;
}
public static BaseLocator getInstance() {
if (baselocator == null)
baselocator = (BaseLocator) factory.getBean("baseLocator");
return baselocator;
}
}
在spring bean裡做個配置
<bean id="baseLocator" class="com.landicorp.wsi.util.BaseLocator" />
其中getInstance()方法作者大約是漏掉了,所以一開始出現了元件父類中retrieveBeanFactory()方法返回BeanFactory為null的情況,搜尋後終於找到原因,於是加上。
被注入的容器子類採用getter/setter方法注入。
public class MyLoginWebService extends BaseWebService
{
private IUserService userService;
public MyLoginWebService() {
super();
System.out.println(userService);
}
public IUserService getUserService() {
return userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
}
獲取到的userService終於不為null了。
成功。