當前位置:編程學習大全網 - 源碼下載 - spring怎麽通過beanfactory來管理對象

spring怎麽通過beanfactory來管理對象

首先先來理解spring中對JavaBean的管理機制。Spring容器所管理的bean對象都是由beanFacotry工廠來實例化,所以要使用pring容器中bean實例對象,必須該類也是由spring容器所管理,否則無法從bean工廠中得到bean實例對象。

Struts 最新版本中是由 我們先拋開struts2專門來看spring,那麽我們就從spring標準配置文件來說起,如果妳要向某個由spring管理的對象中註入壹個對象,我們該如何去做呢?舉例說明:如果由兩個對象A、B,現在需要在B對象中使用A對象,那麽我們通過什麽方式將A註入到B中去呢?首先A、B兩個對象都必須是由spring容器來管理,那麽我們就需要在配置文件定義property 屬性來註入,現在A、B都有spring容器來管理的,那麽我如何得到其中A對象呢?因為AB對象都是由spring容器來創建的,所以要想得到A對象,就首先得到BeanFactory--->GetA(),然後才能拿到A,這時A指向B對象的引用才有值,才能把A註入到B中。

1、 第壹種不推薦的方式:

在spring配置文件中配置如下:Java代碼

定義壹個類變量(靜態的static,這個類的所有實例***享的變量),啟動服務器時,初始化spring時就創建了BeanFactory,在創建BeanFacotry時,就實例化了所有對象。也就說也就創建了壹個roleAssignmentHandler03 對象,放到了它自己容器的那塊內存中,這個對象擁有壹個指向userService的引用,因為我在這裏定義的是類變量。等下次在創建這個對象時,在這個類變量中同樣是有值。但是這種方法並不推薦,這種方式有點浪費內存空間,spring已經給我們創建了對象,但是我們並沒有去使用它。

Java代碼publicclassRoleAssignmentHandler03implementsAssignmentHandler{ privatestaticUserServiceuserService; publicvoidsetUserService(UserService_userService){ userService=_userService; } ……public class RoleAssignmentHandler03 implements AssignmentHandler {private static UserService userService;public void setUserService(UserService _userService) {userService = _userService;}……

2、 第二種不推薦的方式:

我不能向往常做測試那樣通過new ClassPathXmlApplicationContext("");來創建它,我們需要從當前環境中去拿,那麽從什麽地方去拿呢?那麽就得明白它是如何創建的,由誰來創建並管理的?在服務器啟動時,它就會初始化web.xml中的linstener配置信息,創建壹個Bean’Factroy對象,並把這個對象放到了ServletContext中,我們可以利用spring中的壹個工具類來得到ServletContext中的BeanFactory對象,但是並推薦,因為ServletActionContext是Struts中的,在業務邏輯中過分依賴於展現層的內容,JBPM是不依賴於展現層內容的,也不推薦於依賴關系的存在。

Java代碼BeanFactoryfactory=WebApplicationContextUtils.getRequiredWebApplicationContext(ServletActionContext.getServletContext()); UserServiceuserService=factory.getBean("userService");BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletActionContext.getServletContext());UserService userService = factory.getBean("userService");

3、 第三種並不推薦的方式

在項目開發中采用SSH與JBPM集成時,用到了壹個第三方的集成包,我們可以從這裏得到解決方案,(采用jbpm3.1所以其第三方集成包為spring-modules-jbpm31.jar)在其文檔(jbpm31.html)中可以了解到,采用如下配置:

流程定義文件配置Java代碼 roleAssignmentHandler03 roleAssignmentHandler03

在spring配置文件中可以這樣定義如下Java代碼

4、 第四種方式:

回過頭來,我們接著繼續思考從BeanFactory中去獲得,流程定義文件並不去修改它,這樣就不會破壞它的靈活性,那麽接下來要分析的問題就是如何來獲得BeanFactory呢?那就得深入了解壹下spring,現在來看壹個問題:在壹個單例中如何獲得壹個非單例的對象呢?也就是將B註入到A中 A是單例,但是B不是單例,直接采用Resource或在配置文件利用property註入的話,是無法實現的,只能將B變成壹個單例對象來使用。那麽我們在單例對象中如何動態獲取依賴對象呢?有壹種方式就從它的BeanFactory中去獲得其對象,如何在由spring管理的對象中拿到BeanFactory呢?也就是說在容器實例對象中訪問容器本身,在spring中有這樣壹個BeanFactoryAware接口,在這個接口有個setBeanFactory(BeanFactory f)方法,我們可以實現該接口,重寫這個方法,來得到我們BeanFactory,從中得到動態的得到BeanFactory中實例對象,但是放到jbpm中handler類中來使用,還是無法實現的,因為在這裏它不是有spring來管理的,所以即使實現BeanFactory接口,重寫其方法,但是無法將BeanFactory設置上值的,因為它是由spring來管理的,所以我無法從壹個不是spring所管理的bean中去註入spring所提供的bean對象。但是我們可以通過另壹種途徑來解決這個問題:創建壹個輔助類BeanFactroyHelper類,讓它來實現剛才這個BeanFactoryAware接口,具體如下:Java代碼publicclassBeanFactoryHelperimplementsBeanFactoryAware{ privatestaticBeanFactoryfactory; publicvoidsetBeanFactory(BeanFactoryf)throwsBeansException{ factory=f; } publicstaticBeanFactorygetFactory(){ returnfactory; } }public class BeanFactoryHelper implements BeanFactoryAware {private static BeanFactory factory;public void setBeanFactory(BeanFactory f) throws BeansException {factory = f;}public static BeanFactory getFactory(){return factory;}}

然後,讓上面這個類納入spring的管理,在spring中配置如下:Java代碼

最後在我們handler類中,直接使用就可以了Java代碼BeanFactoryfactory=BeanFactoryHelper.getFactory();BeanFactory factory = BeanFactoryHelper.getFactory();

這種方式可以,但是我並采用這種方式,因為第四種方式已經有人給我做了。所以我們就不需要在重復做這些類似的工作了。所以這種方式我也不會采用。

5、 第五種方式:

通過上面所說的方式,在spring-modules.jar這個第三方集成包開發人中已經采用類似的方式實現了。那麽他們是如何實現的呢?這就需要來了解壹下jbpmHandlerProxy的基本原理,在JbpmHandlerProxy類中實現了ActionHandler, AssignmentHandler, DecisionHandler, TaskControllerHandler等接口,在實現不同的接口會調用不同它的不同的方法execute、assign、decide…

ServiceLocator,在spring中也提供了壹個ServiceLocator這種設計模式的壹個接口BeanFactoryLocator、 BeanFactoryReference接口,要想詳細了解其內部機制需要我們進壹步花費精力去解析其源碼了。(在這裏就不詳細去分析了)這裏我只是了解jbpmFactoryPorxy類中實現機制的大體思想,所以下面我就針對在代理類中的具體實現思想大體說壹下:在JbpmHandlerProxy類中得到BeanFactory對象,主要是通過JbpmFactoryLocator來得到BeanFactoryReference,通過BeanFactoryReference來得到Factory。那麽在JbpmHandlerProxy類中的JbpmFactoryLocator是從哪裏得到的呢?查看源碼可以得知在其JbpmFactoryLocator類下有個setBeanFactory()方法,那麽這個方法是有誰調用的呢?通過查看得知是LocalJbpmConfigurationFactoryBean類來調用的。主要分析圖如下:

以上就jbpmFactoryProxy中內部機制。

下面我就來說壹下具體解決方案是:

首先通過利用jbpmFactoryProxy的實現類中retrieveBeanFactory方法的具體實現方式,來得到jbpm中已經註入的BeanFactory對象,下面我將進壹步進行封裝來實現自動註入的功能。

先貼出在jbpm的handler類中的具體使用,和在spring中使用Bean對象壹樣使用。

Java代碼/** *是由BaseAutowire自動註入 */@ResourceprivateUserServiceuserServce;/*** 是由BaseAutowire自動註入*/@Resourceprivate UserService userServce;下面壹段代碼將是所抽取出來的基類:Java代碼/** *自動註入BeanFactory基類 *@authorlzh * */publicclassBaseAutowire{ /** *在調用子類的時會自動調用 *在構造方法中調用retrieveBeanFactory()方法得到BeanFactory對象 *利用它的實現接口設置將該自身設置為自動註入到子類中 */publicBaseAutowire(){ ((AutowireCapableBeanFactory)retrieveBeanFactory()) .autowireBeanProperties(this,AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE,true); } protectedBeanFactoryretrieveBeanFactory(){ BeanFactoryLocatorfactoryLocator=newJbpmFactoryLocator(); BeanFactoryReferencefactory=factoryLocator.useBeanFactory(null); if(factory==null) thrownewIllegalArgumentException("nobeanFactoryfoundunderkey="+null); try{ returnfactory.getFactory(); } finally{ factory.release(); } } }/*** 自動註入BeanFactory基類* @author lzh**/public class BaseAutowire {/*** 在調用子類的時會自動調用* 在構造方法中調用retrieveBeanFactory()方法得到BeanFactory對象* 利用它的實現接口設置將該自身設置為自動註入到子類中*/public BaseAutowire() {((AutowireCapableBeanFactory)retrieveBeanFactory()).autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);}protected BeanFactory retrieveBeanFactory() {BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();BeanFactoryReference factory = factoryLocator.useBeanFactory(null);if (factory == null)throw new IllegalArgumentException("no beanFactory found under key=" + null);try {return factory.getFactory();}finally {factory.release();}}}

  • 上一篇:什麽是3dmax?
  • 下一篇:vivo怎麽圖片識別
  • copyright 2024編程學習大全網