1. 程式人生 > >通過反射途徑獲得的物件如何自動注入spring Bean

通過反射途徑獲得的物件如何自動注入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了。

成功。