Spring BeanFactory與FactoryBean的區別及其各自的詳細介紹於用法
阿新 • • 發佈:2018-08-25
排除 tle 判斷 service 關系 符號 它的 extc ()
1. BeanFactory
BeanFactory,以Factory結尾,表示它是一個工廠類(接口),用於管理Bean的一個工廠。在Spring中,BeanFactory是IOC容器的核心接口,它的職責包括:實例化、定位、配置應用程序中的對象及建立這些對象間的依賴。
Spring為我們提供了許多易用的BeanFactory實現,XmlBeanFactory就是常用的一個,該實現將以XML方式描述組成應用的對象及對象間的依賴關系。XmlBeanFactory類將持有此XML配置元數據,並用它來構建一個完全可配置的系統或應用。
實例化容器
1 Resource resource = new FileSystemResource("beans.xml"); 2 BeanFactory factory = new XmlBeanFactory(resource);
1 ClassPathResource resource = new ClassPathResource("beans.xml"); 2 BeanFactory factory = new XmlBeanFactory(resource);
1 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"}); 3 BeanFactory factory = (BeanFactory) context;
基本就是這些了,接著使用getBean(String beanName)方法就可以取得bean的實例;BeanFactory提供的方法及其簡單,僅提供了六種方法供客戶調用:
- boolean containsBean(String beanName) 判斷工廠中是否包含給定名稱的bean定義,若有則返回true
- Object getBean(String) 返回給定名稱註冊的bean實例。根據bean的配置情況,如果是singleton模式將返回一個共享實例,否則將返回一個新建的實例,如果沒有找到指定bean,該方法可能會拋出異常
- Object getBean(String, Class) 返回以給定名稱註冊的bean實例,並轉換為給定class類型
- Class getType(String name) 返回給定名稱的bean的Class,如果沒有找到指定的bean實例,則排除NoSuchBeanDefinitionException異常
- boolean isSingleton(String) 判斷給定名稱的bean定義是否為單例模式
- String[] getAliases(String name) 返回給定bean名稱的所有別名
2. FactoryBean
以Bean結尾,表示它是一個Bean,不同於普通Bean的是:它是實現了FactoryBean<T>接口的Bean,根據該Bean的ID從FactoryBean中獲取的實際上是FactoryBean的getObject()返回的對象,而不是FactoryBean本身,如果要獲取FactoryBean對象,請在id前面加一個&符號來獲取。
例如自己實現一個FactoryBean,功能:用來代理一個對象,對該對象的所有方法做一個攔截,在調用前後都輸出一行LOG,模仿ProxyFactoryBean的功能。
1 /** 2 * my factory bean<p> 3 * 代理一個類,攔截該類的所有方法,在方法的調用前後進行日誌的輸出 4 * @author daniel.zhao 5 * 6 */ 7 public class MyFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean { 8 9 private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class); 10 11 private String interfaceName; 12 13 private Object target; 14 15 private Object proxyObj; 16 17 @Override 18 public void destroy() throws Exception { 19 logger.debug("destroy......"); 20 } 21 22 @Override 23 public void afterPropertiesSet() throws Exception { 24 proxyObj = Proxy.newProxyInstance( 25 this.getClass().getClassLoader(), 26 new Class[] { Class.forName(interfaceName) }, 27 new InvocationHandler() { 28 29 @Override 30 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 31 logger.debug("invoke method......" + method.getName()); 32 logger.debug("invoke method before......" + System.currentTimeMillis()); 33 Object result = method.invoke(target, args); 34 logger.debug("invoke method after......" + System.currentTimeMillis()); 35 return result; 36 } 37 38 }); 39 logger.debug("afterPropertiesSet......"); 40 } 41 42 @Override 43 public Object getObject() throws Exception { 44 logger.debug("getObject......"); 45 return proxyObj; 46 } 47 48 @Override 49 public Class<?> getObjectType() { 50 return proxyObj == null ? Object.class : proxyObj.getClass(); 51 } 52 53 @Override 54 public boolean isSingleton() { 55 return true; 56 } 57 58 public String getInterfaceName() { 59 return interfaceName; 60 } 61 62 public void setInterfaceName(String interfaceName) { 63 this.interfaceName = interfaceName; 64 } 65 66 public Object getTarget() { 67 return target; 68 } 69 70 public void setTarget(Object target) { 71 this.target = target; 72 } 73 74 public Object getProxyObj() { 75 return proxyObj; 76 } 77 78 public void setProxyObj(Object proxyObj) { 79 this.proxyObj = proxyObj; 80 } 81 82 }
XML-Bean配置如下
1 <bean id="fbHelloWorldService" class="com.ebao.xxx.MyFactoryBean"> 2 <property name="interfaceName" value="com.ebao.xxx.HelloWorldService" /> 3 <property name="target" ref="helloWorldService" /> 4 </bean>
Junit Test class
1 @RunWith(JUnit4ClassRunner.class) 2 @ContextConfiguration(classes = { MyFactoryBeanConfig.class }) 3 public class MyFactoryBeanTest { 4 5 @Autowired 6 private ApplicationContext context; 7 8 /** 9 * 測試驗證FactoryBean原理,代理一個servcie在調用其方法的前後,打印日誌亦可作其他處理 10 * 從ApplicationContext中獲取自定義的FactoryBean 11 * context.getBean(String beanName) ---> 最終獲取到的Object是FactoryBean.getObejct(), 12 * 使用Proxy.newInstance生成service的代理類 13 */ 14 @Test 15 public void testFactoryBean() { 16 HelloWorldService helloWorldService = (HelloWorldService) context.getBean("fbHelloWorldService"); 17 helloWorldService.getBeanName(); 18 helloWorldService.sayHello(); 19 } 20 }
其實FactoryBean這棟特點,可以實現很多有用的功能,實現大家多多評論多多補充,一起探討。
Spring BeanFactory與FactoryBean的區別及其各自的詳細介紹於用法