被问懵了,BeanFactory和FactoryBean接口的区别到底是什么?
作者:ゞ .鄧澎波
cnblogs.com/dengpengbo/p/10493782.html
目錄
一、BeanFactory接口
二、FactoryBean接口
1.簡單實現
2.增強實現
3.FactoryBean的實際使用案例
三、總結
Spring框架中的BeanFactory接口和FactoryBean接口因為名稱相似,老是容易搞混淆,而且也是面試過程中經常會碰到的一個問題。所以本文就專門給大家整理出來。
一、BeanFactory接口
BeanFactory接口是Spring容器的核心接口,負責:實例化、定位、配置應用程序中的對象及建立這些對象間的依賴。
在這里插入圖片描述Spring為我們提供了許多易用的BeanFactory實現,XmlBeanFactory就是常用的一個,該實現將以XML方式描述組成應用的對象及對象間的依賴關系。XmlBeanFactory類將持有此XML配置元數據,并用它來構建一個完全可配置的系統或應用。
BeanFactory?bf?=?new?XmlBeanFactory(new?ClassPathResource("applicationContext.xml")); Object?bean?=??bf.getBean(IUserService.class); System.out.println(bean);接口中定義的方法
public?interface?BeanFactory?{String?FACTORY_BEAN_PREFIX?=?"&";Object?getBean(String?name)?throws?BeansException;<T>?T?getBean(String?name,?Class<T>?requiredType)?throws?BeansException;Object?getBean(String?name,?Object...?args)?throws?BeansException;<T>?T?getBean(Class<T>?requiredType)?throws?BeansException;<T>?T?getBean(Class<T>?requiredType,?Object...?args)?throws?BeansException;boolean?containsBean(String?name);boolean?isSingleton(String?name)?throws?NoSuchBeanDefinitionException;boolean?isPrototype(String?name)?throws?NoSuchBeanDefinitionException;boolean?isTypeMatch(String?name,?ResolvableType?typeToMatch)?throws?NoSuchBeanDefinitionException;boolean?isTypeMatch(String?name,?Class<?>?typeToMatch)?throws?NoSuchBeanDefinitionException;Class<?>?getType(String?name)?throws?NoSuchBeanDefinitionException;String[]?getAliases(String?name); }二、FactoryBean接口
BeanFactory接口是Spring的核心接口。功能非常復雜,這個時候如果我們想要編寫一些比較復雜點兒的邏輯就會觸及到其他一些不必要的接口,不好實現。
這時候使用FactoryBean就比較方便了。FactoryBean以Bean結尾是個Bean對象,不是工廠。接口中定義的方法如下:
public?interface?FactoryBean<T>?{/***?返回對象的實例*/T?getObject()?throws?Exception;/***?返回對象的類型*/Class<?>?getObjectType();/***?是否是單例*/boolean?isSingleton(); }1.簡單實現
接口和實現類
public?interface?IUserService?{public?void?doSome(); } public?class?UserServiceImpl?implements?IUserService?{public?UserServiceImpl(){System.out.println("--被實例化了--");}@Overridepublic?void?doSome()?{System.out.println("UserServiceImpl 。。。?被執行了");}}自定義FactoryBean
public?class?MyFactoryBean?implements?FactoryBean<IUserService>{@Overridepublic?IUserService?getObject()?throws?Exception?{System.out.println("--IUserService實例化之前---");IUserService?service?=?new?UserServiceImpl();System.out.println("--IUserService實例化后---");return?service;}@Overridepublic?Class<?>?getObjectType()?{return?IUserService.class;}@Overridepublic?boolean?isSingleton()?{return?true;} }配置文件
<?xml?version="1.0"?encoding="UTF-8"?> <beans?xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd"><bean?id="myFactoryBean"?class="com.dpb.factorybean.MyFactoryBean"/> </beans>測試--通過類型獲取
@Test public?void?test1()?{BeanFactory?bf?=?new?XmlBeanFactory(new?ClassPathResource("applicationContext.xml"));Object?bean?=??bf.getBean(IUserService.class);System.out.println(bean); }輸出結果
--IUserService實例化之前--- --被實例化了-- --IUserService實例化后--- com.dpb.service.UserServiceImpl@5315b42e測試--通過id獲取
@Test public?void?test1()?{BeanFactory?bf?=?new?XmlBeanFactory(new?ClassPathResource("applicationContext.xml"));Object?bean?=??bf.getBean("myFactoryBean");System.out.println(bean); }輸出結果
--IUserService實例化之前--- --被實例化了-- --IUserService實例化后--- com.dpb.service.UserServiceImpl@783e6358如果想要獲取FactoryBean對象 id前加 &就可以
@Test public?void?test1()?{BeanFactory?bf?=?new?XmlBeanFactory(new?ClassPathResource("applicationContext.xml"));Object?bean?=??bf.getBean("&myFactoryBean");System.out.println(bean); }輸出結果
com.dpb.factorybean.MyFactoryBean@3b81a1bc2.增強實現
通過FactoryBean創建一個代理類來增強目標類,我們來看下效果
接口和實現類
public?interface?IUserService?{public?void?doSome(); } public?class?UserServiceImpl?implements?IUserService?{public?UserServiceImpl(){System.out.println("--被實例化了--");}@Overridepublic?void?doSome()?{System.out.println("UserServiceImpl 。。。?被執行了");}}自定義FactoryBean
public?class?MyFactoryBean?implements?FactoryBean,InitializingBean,DisposableBean{private?Object?proxyObject;private?Object?target;private?String?interfaceName;@Overridepublic?Object?getObject()?throws?Exception?{return?proxyObject;}@Overridepublic?Class<?>?getObjectType()?{return?proxyObject.getClass()==null?Object.class:proxyObject.getClass();}@Overridepublic?boolean?isSingleton()?{return?true;}/***?MyFactoryBean?對象銷毀的回調方法*?@throws?Exception*/@Overridepublic?void?destroy()?throws?Exception?{System.out.println("destroy?....");}/***?MyFactoryBean?對象實例化的方法*/@Overridepublic?void?afterPropertiesSet()?throws?Exception?{System.out.println("---afterPropertiesSet---");proxyObject?=?Proxy.newProxyInstance(this.getClass().getClassLoader(),?new?Class[]{Class.forName(interfaceName)},?new?InvocationHandler()?{@Overridepublic?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{System.out.println("----代理方法執行開始----");Object?obj?=?method.invoke(target,?args);System.out.println("----代理方法執行結束----");return?obj;}});}public?String?getInterfaceName()?{return?interfaceName;}public?void?setInterfaceName(String?interfaceName)?{this.interfaceName?=?interfaceName;}public?Object?getTarget()?{return?target;}public?void?setTarget(Object?target)?{this.target?=?target;} }配置文件
<?xml?version="1.0"?encoding="UTF-8"?> <beans?xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd"><!--?注冊目標對象?--><bean?class="com.dpb.service.UserServiceImpl"?id="userServiceImpl"/><!--?注冊FactoryBean對象?--><bean?id="myFactoryBean"?class="com.dpb.factorybean.MyFactoryBean"><property?name="interfaceName"?value="com.dpb.service.IUserService"/><property?name="target"?ref="userServiceImpl"/>?</bean> </beans>測試
@Test public?void?test1()?{ApplicationContext?ac?=?new?ClassPathXmlApplicationContext("applicationContext.xml");IUserService?bean?=???(IUserService)?ac.getBean("myFactoryBean");System.out.println("****************");bean.doSome();System.out.println(); }輸出結果:
--被實例化了-- ---afterPropertiesSet--- **************** ----代理方法執行開始---- UserServiceImpl 。。。?被執行了 ----代理方法執行結束----小結:通過輸出結果我們可以看到通過FactoryBean接口我們也可以實現BeanFactory中某些接口提供的功能,而且會更加的靈活一些。
3.FactoryBean的實際使用案例
Spring在整合mybatis框架的時候提供的SqlSessionFactoryBean就是FactoryBean的很好的實現。
<!--?整合mybatis?--> <bean?class="org.mybatis.spring.SqlSessionFactoryBean"? id="sqlSessionFactoryBean"?><!--?關聯數據源?--><property?name="dataSource"?ref="dataSource"/><!--?關聯mybatis的配置文件?--><property?name="configLocation"?value="classpath:mybatis-cfg.xml"/><!--?添加別名設置?--><property?name="typeAliasesPackage"?value="com.sxt.model"/><!--?映射文件和接口文件不在同一個目錄下的時候,需要單獨指定映射文件的路徑?--><property?name="mapperLocations"?value="classpath:mapper/*.xml"/> </bean>Spring會調用SqlSessionFactoryBean這個實現了FactoryBean的工廠Bean 同時加載dataSource,Mapper文件的路徑,對sqlSessionFactory進行初始化。
源代碼比較多就不一一貼出來。到了這兒可以自行跟蹤下源代碼。
核心方法
@Overridepublic?void?afterPropertiesSet()?throws?Exception?{//?省略this.sqlSessionFactory?=?buildSqlSessionFactory();}protected?SqlSessionFactory?buildSqlSessionFactory()?throws?IOException?{Configuration?configuration;XMLConfigBuilder?xmlConfigBuilder?=?null;//?省略return?this.sqlSessionFactoryBuilder.build(configuration);} /***?{@inheritDoc}*/@Overridepublic?SqlSessionFactory?getObject()?throws?Exception?{if?(this.sqlSessionFactory?==?null)?{afterPropertiesSet();}return?this.sqlSessionFactory;}/***?{@inheritDoc}*/@Overridepublic?Class<??extends?SqlSessionFactory>?getObjectType()?{return?this.sqlSessionFactory?==?null???SqlSessionFactory.class?:?this.sqlSessionFactory.getClass();}/***?{@inheritDoc}*/@Overridepublic?boolean?isSingleton()?{return?true;}maven坐標:
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.2</version> </dependency>三、總結
BeanFactory是Spring中IOC容器最核心的接口,遵循了IOC容器中所需的基本接口。例如我們很常見的:ApplicationContext,XmlBeanFactory 等等都使用了BeanFactory這個接口。
FactoryBean是工廠類接口,當你只是想簡單的去構造Bean,不希望實現原有大量的方法。它是一個Bean,不過這個Bean能夠做為工廠去創建Bean,同時還能修飾對象的生成。
FactoryBean比BeanFactory在生產Bean的時候靈活,還能修飾對象,帶有工廠模式和裝飾模式的意思在里面,不過它的存在還是以Bean的形式存在。
面試官問:前后端分離項目,有什么優缺點?我說:沒
2020 年騰訊新增 20 億行代碼,鵝廠第一編程語言還是它
通俗講解分布式鎖,看完不懂算我輸
寫博客能月入10K?
一款基于 Spring Boot 的現代化社區(論壇/問答/社交網絡/博客)
這或許是最美的Vue+Element開源后臺管理UI
推薦一款高顏值的 Spring Boot 快速開發框架
一款基于 Spring Boot 的現代化社區(論壇/問答/社交網絡/博客)
13K點贊都基于 Vue+Spring 前后端分離管理系統ELAdmin,大愛
想接私活時薪再翻一倍,建議根據這幾個開源的SpringBoot項目
總結
以上是生活随笔為你收集整理的被问懵了,BeanFactory和FactoryBean接口的区别到底是什么?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有了这篇你还说你不会redis性能优化、
- 下一篇: 曲面屏敲代码飞起,包邮送到家!