<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    一道阿里面試題:說說你知道的關(guān)于BeanFactory和FactoryBean的區(qū)別

    共 27906字,需瀏覽 56分鐘

     ·

    2022-07-04 13:30

    BeanFacotry是spring中比較原始的Factory。如XMLBeanFactory就是一種典型的BeanFactory。原始的BeanFactory無法支持spring的許多插件,如AOP功能、Web應(yīng)用等。

    ApplicationContext接口,它由BeanFactory接口派生而來。ApplicationContext包含BeanFactory的所有功能,通常建議比BeanFactory優(yōu)先。

    BeanFactory和FactoryBean的區(qū)別

    BeanFactory是接口,提供了OC容器最基本的形式,給具體的IOC容器的實現(xiàn)提供了規(guī)范,

    FactoryBean也是接口,為IOC容器中Bean的實現(xiàn)提供了更加靈活的方式,F(xiàn)actoryBean在IOC容器的基礎(chǔ)上給Bean的實現(xiàn)加上了一個簡單工廠模式和裝飾模式(如果想了解裝飾模式參考:修飾者模式(裝飾者模式,Decoration) 我們可以在getObject()方法中靈活配置。其實在Spring源碼中有很多FactoryBean的實現(xiàn)類.

    區(qū)別:BeanFactory是個Factory,也就是IOC容器或?qū)ο蠊S,F(xiàn)actoryBean是個Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)來進(jìn)行管理的。

    對FactoryBean而言,這個Bean不是簡單的Bean,而是一個能生產(chǎn)或者修飾對象生成的工廠Bean,它的實現(xiàn)與設(shè)計模式中的工廠模式和修飾器模式類似

    1、BeanFactory

    BeanFactory,以Factory結(jié)尾,表示它是一個工廠類(接口), 它負(fù)責(zé)生產(chǎn)和管理bean的一個工廠。在Spring中,BeanFactory是IOC容器的核心接口,它的職責(zé)包括:實例化、定位、配置應(yīng)用程序中的對象及建立這些對象間的依賴。

    BeanFactory只是個接口,并不是IOC容器的具體實現(xiàn),但是Spring容器給出了很多種實現(xiàn),如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一個,該實現(xiàn)將以XML方式描述組成應(yīng)用的對象及對象間的依賴關(guān)系。XmlBeanFactory類將持有此XML配置元數(shù)據(jù),并用它來構(gòu)建一個完全可配置的系統(tǒng)或應(yīng)用。

    都是附加了某種功能的實現(xiàn)。它為其他具體的IOC容器提供了最基本的規(guī)范,例如DefaultListableBeanFactory,XmlBeanFactory,ApplicationContext 等具體的容器都是實現(xiàn)了BeanFactory,再在其基礎(chǔ)之上附加了其他的功能。

    BeanFactory和ApplicationContext就是spring框架的兩個IOC容器,現(xiàn)在一般使用ApplicationnContext,其不但包含了BeanFactory的作用,同時還進(jìn)行更多的擴(kuò)展。

    BeanFacotry是spring中比較原始的Factory。如XMLBeanFactory就是一種典型的BeanFactory。

    原始的BeanFactory無法支持spring的許多插件,如AOP功能、Web應(yīng)用等。ApplicationContext接口,它由BeanFactory接口派生而來,

    ApplicationContext包含BeanFactory的所有功能,通常建議比BeanFactory優(yōu)先

    ApplicationContext以一種更向面向框架的方式工作以及對上下文進(jìn)行分層和實現(xiàn)繼承,ApplicationContext包還提供了以下的功能:

    • MessageSource, 提供國際化的消息訪問

    • 資源訪問,如URL和文件

    • 事件傳播

    • 載入多個(有繼承關(guān)系)上下文 ,使得每一個上下文都專注于一個特定的層次,比如應(yīng)用的web層;

    在不使用spring框架之前,我們的service層中要使用dao層的對象,不得不在service層中new一個對象。存在的問題:層與層之間的依賴。

    service層要用dao層對象需要配置到xml配置文件中,至于對象是怎么創(chuàng)建的,關(guān)系是怎么組合的都交給了spring框架去實現(xiàn)。

    方式1、

    Resource resource = new FileSystemResource("beans.xml");
    BeanFactory factory = new XmlBeanFactory(resource);

    方式2、

    ClassPathResource resource = new ClassPathResource("beans.xml");
    BeanFactory factory = new XmlBeanFactory(resource);

    方式3、

    ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml""applicationContext-part2.xml"});
    BeanFactory factory = (BeanFactory) context;

    基本就是這些了,接著使用getBean(String beanName)方法就可以取得bean的實例;BeanFactory提供的方法及其簡單,僅提供了六種方法供客戶調(diào)用:

    • boolean containsBean(String beanName) 判斷工廠中是否包含給定名稱的bean定義,若有則返回true

    • Object getBean(String) 返回給定名稱注冊的bean實例。根據(jù)bean的配置情況,如果是singleton模式將返回一個共享實例,否則將返回一個新建的實例,如果沒有找到指定bean,該方法可能會拋出異常

    • Object getBean(String, Class) 返回以給定名稱注冊的bean實例,并轉(zhuǎn)換為給定class類型

    • Class getType(String name) 返回給定名稱的bean的Class,如果沒有找到指定的bean實例,則排除NoSuchBeanDefinitionException異常

    • boolean isSingleton(String) 判斷給定名稱的bean定義是否為單例模式

    • String[] getAliases(String name) 返回給定bean名稱的所有別名


    package org.springframework.beans.factory;  
    import org.springframework.beans.BeansException;  
    public interface BeanFactory {  
        String FACTORY_BEAN_PREFIX = "&";  
        Object getBean(String name) throws BeansException;  
        <T> getBean(String name, Class<T> requiredType) throws BeansException;  
        <T> getBean(Class<T> requiredType) throws BeansException;  
        Object getBean(String name, Object... args) throws BeansException;  
        boolean containsBean(String name);  
        boolean isSingleton(String name) throws NoSuchBeanDefinitionException;  
        boolean isPrototype(String name) throws NoSuchBeanDefinitionException;  
        boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;  
        Class<?> getType(String name) throws NoSuchBeanDefinitionException;  
        String[] getAliases(String name);  
    }

    2、FactoryBean

    一般情況下,Spring通過反射機(jī)制利用<bean>的class屬性指定實現(xiàn)類實例化Bean,在某些情況下,實例化Bean過程比較復(fù)雜,如果按照傳統(tǒng)的方式,則需要在<bean>中提供大量的配置信息。配置方式的靈活性是受限的,這時采用編碼的方式可能會得到一個簡單的方案。

    Spring為此提供了一個org.springframework.bean.factory.FactoryBean的工廠類接口,用戶可以通過實現(xiàn)該接口定制實例化Bean的邏輯。FactoryBean接口對于Spring框架來說占用重要的地位,Spring自身就提供了70多個FactoryBean的實現(xiàn)。它們隱藏了實例化一些復(fù)雜Bean的細(xì)節(jié),給上層應(yīng)用帶來了便利。從Spring3.0開始,F(xiàn)actoryBean開始支持泛型,即接口聲明改為FactoryBean<T>的形式

    以Bean結(jié)尾,表示它是一個Bean,不同于普通Bean的是:它是實現(xiàn)了FactoryBean<T>接口的Bean,根據(jù)該Bean的ID從BeanFactory中獲取的實際上是FactoryBean的getObject()返回的對象,而不是FactoryBean本身,如果要獲取FactoryBean對象,請在id前面加一個&符號來獲取。

    例如自己實現(xiàn)一個FactoryBean,功能:用來代理一個對象,對該對象的所有方法做一個攔截,在調(diào)用前后都輸出一行LOG,模仿ProxyFactoryBean的功能。

    /**
     * my factory bean<p>
     * 代理一個類,攔截該類的所有方法,在方法的調(diào)用前后進(jìn)行日志的輸出
     * @author daniel.zhao
     *
     */

    public class MyFactoryBean implements FactoryBean<Object>, InitializingBeanDisposableBean {

        private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class);    
        private String interfaceName;    
        private Object target;    
        private Object proxyObj;    
        @Override
        public void destroy() throws Exception {
            logger.debug("destroy......");
        }
        @Override
        public void afterPropertiesSet() throws Exception {
            proxyObj = Proxy.newProxyInstance(
                    this.getClass().getClassLoader(), 
                    new Class[] { Class.forName(interfaceName) }, 
                    new InvocationHandler() {                    
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    logger.debug("invoke method......" + method.getName());
                    logger.debug("invoke method before......" + System.currentTimeMillis());
                    Object result = method.invoke(target, args);
                    logger.debug("invoke method after......" + System.currentTimeMillis());
                    return result;            }            
            });
            logger.debug("afterPropertiesSet......");
        }

        @Override
        public Object getObject() throws Exception {
            logger.debug("getObject......");
            return proxyObj;
        }

        @Override
        public Class<?> getObjectType() {
            return proxyObj == null ? Object.class : proxyObj.getClass();
        }

        @Override
        public boolean isSingleton() {
            return true;
        }

        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;
        }

        public Object getProxyObj() {
            return proxyObj;
        }

        public void setProxyObj(Object proxyObj) {
            this.proxyObj = proxyObj;
        }

    }

    XML-Bean配置如下

    <bean id="fbHelloWorldService" class="com.ebao.xxx.MyFactoryBean">
       <property name="interfaceName" value="com.ebao.xxx.HelloWorldService" />
       <property name="target" ref="helloWorldService" />
    </bean>

    Junit Test class

    @RunWith(JUnit4ClassRunner.class)
    @ContextConfiguration(classes = { MyFactoryBeanConfig.class })
    public class MyFactoryBeanTest {
        @Autowired
        private ApplicationContext context;    
        /**
         * 測試驗證FactoryBean原理,代理一個servcie在調(diào)用其方法的前后,打印日志亦可作其他處理
         * 從ApplicationContext中獲取自定義的FactoryBean
         * context.getBean(String beanName) ---> 最終獲取到的Object是FactoryBean.getObejct(), 
         * 使用Proxy.newInstance生成service的代理類
         */

        @Test
        public void testFactoryBean() {
            HelloWorldService helloWorldService = (HelloWorldService) context.getBean("fbHelloWorldService");
            helloWorldService.getBeanName();
            helloWorldService.sayHello();
        }
    }

    FactoryBean是一個接口,當(dāng)在IOC容器中的Bean實現(xiàn)了FactoryBean后,通過getBean(String BeanName)獲取到的Bean對象并不是FactoryBean的實現(xiàn)類對象,而是這個實現(xiàn)類中的getObject()方法返回的對象。要想獲取FactoryBean的實現(xiàn)類,就要getBean(&BeanName),在BeanName之前加上&。

    Java代碼

    package org.springframework.beans.factory;  
    public interface FactoryBean<T{  
        getObject() throws Exception;  
        Class<?> getObjectType();  
        boolean isSingleton();  
    }

    在該接口中還定義了以下3個方法:

    • TgetObject():返回由FactoryBean創(chuàng)建的Bean實例,如果isSingleton()返回true,則該實例會放到Spring容器中單實例緩存池中;

    • booleanisSingleton():返回由FactoryBean創(chuàng)建的Bean實例的作用域是singleton還是prototype;

    • Class<T>getObjectType():返回FactoryBean創(chuàng)建的Bean類型。

    當(dāng)配置文件中<bean>的class屬性配置的實現(xiàn)類是FactoryBean時,通過getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的對象,相當(dāng)于FactoryBean#getObject()代理了getBean()方法。

    例:如果使用傳統(tǒng)方式配置下面Car的<bean>時,Car的每個屬性分別對應(yīng)一個<property>元素標(biāo)簽。

    package  com.baobaotao.factorybean;  
        public   class  Car  {  
            private   int maxSpeed ;  
            private  String brand ;  
            private   double price ;  
            public   int  getMaxSpeed ()   {  
                return   this . maxSpeed ;  
            }  
            public   void  setMaxSpeed int  maxSpeed )   {  
                this . maxSpeed  = maxSpeed;  
            }  
            public  String getBrand ()   {  
                return   this . brand ;  
            }  
            public   void  setBrand ( String brand )   {  
                this . brand  = brand;  
            }  
            public   double  getPrice ()   {  
                return   this . price ;  
            }  
            public   void  setPrice double  price )   {  
                this . price  = price;  
           }  
    }

    如果用FactoryBean的方式實現(xiàn)就靈活點,下例通過逗號分割符的方式一次性的為Car的所有屬性指定配置值:

    package  com.baobaotao.factorybean;  
    import  org.springframework.beans.factory.FactoryBean;  
    public   class  CarFactoryBean  implements  FactoryBean<Car>  {  
        private  String carInfo ;  
        public  Car getObject ()   throws  Exception  {  
            Car car =  new  Car () ;  
            String []  infos =  carInfo .split ( "," ) ;  
            car.setBrand ( infos [ 0 ]) ;  
            car.setMaxSpeed ( Integer. valueOf ( infos [ 1 ])) ;  
            car.setPrice ( Double. valueOf ( infos [ 2 ])) ;  
            return  car;  
        }  
        public  Class<Car> getObjectType ()   {  
            return  Car. class ;  
        }  
        public   boolean  isSingleton ()   {  
            return   false ;  
        }  
        public  String getCarInfo ()   {  
            return   this . carInfo ;  
        }  

        // 接受逗號分割符設(shè)置屬性信息  
        public   void  setCarInfo ( String carInfo )   {  
            this . carInfo  = carInfo;  
        }  
    }

    有了這個CarFactoryBean后,就可以在配置文件中使用下面這種自定義的配置方式配置CarBean了:

    <bean d="car"class="com.baobaotao.factorybean.CarFactoryBean"
    P:carInfo="法拉利,400,2000000"/>

    當(dāng)調(diào)用getBean("car")時,Spring通過反射機(jī)制發(fā)現(xiàn)CarFactoryBean實現(xiàn)了FactoryBean的接口,這時Spring容器就調(diào)用接口方法CarFactoryBean#getObject()方法返回。如果希望獲取CarFactoryBean的實例,則需要在使用getBean(beanName)方法時在beanName前顯示的加上"&"前綴:如getBean("&car");

    下面是一個應(yīng)用FactoryBean的例子

    <beans xmlns="http://www.springframework.org/schema/beans"  
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
                 xmlns:context="http://www.springframework.org/schema/context"  
                 xmlns:aop="http://www.springframework.org/schema/aop"  
                 xmlns:tx="http://www.springframework.org/schema/tx"  
                 xsi:schemaLocation="http://www.springframework.org/schema/beans  
                         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
                         http://www.springframework.org/schema/context  
                         http://www.springframework.org/schema/context/spring-context-3.0.xsd  
                         http://www.springframework.org/schema/aop  
                         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
                         http://www.springframework.org/schema/tx  
                         http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
    >
      

     <bean id="student" class="com.spring.bean.Student">    
      <property name="name" value="zhangsan" />    
     </bean>    

     <bean id="school" class="com.spring.bean.School">    
     </bean>   

     <bean id="factoryBeanPojo" class="com.spring.bean.FactoryBeanPojo">    
        <property name="type" value="student" />  
     </bean>   
    </beans>

    FactoryBean的實現(xiàn)類

    import org.springframework.beans.factory.FactoryBean;  

    /**  
     * @author  作者 wangbiao 
     * @parameter  
     * @return  
     */
      
    public class FactoryBeanPojo implements FactoryBean{  
        private String type;  

        @Override  
        public Object getObject() throws Exception {  
            if("student".equals(type)){  
                return new Student();             
            }else{  
                return new School();  
            }  

        }  

        @Override  
        public Class getObjectType() {  
            return School.class;  
        }  

        @Override  
        public boolean isSingleton() {  
            return true;  
        }  

        public String getType() {  
            return type;  
        }  

        public void setType(String type) {  
            this.type = type;  
        }  

    }

    普通的bean

    /**  
     * @author  作者 wangbiao 
     * @parameter  
     * @return  
     */
      
    public class School {  
        private String schoolName;  
        private String address;  
        private int studentNumber;  
        public String getSchoolName() {  
            return schoolName;  
        }  
        public void setSchoolName(String schoolName) {  
            this.schoolName = schoolName;  
        }  
        public String getAddress() {  
            return address;  
        }  
        public void setAddress(String address) {  
            this.address = address;  
        }  
        public int getStudentNumber() {  
            return studentNumber;  
        }  
        public void setStudentNumber(int studentNumber) {  
            this.studentNumber = studentNumber;  
        }  
        @Override  
        public String toString() {  
            return "School [schoolName=" + schoolName + ", address=" + address  
                    + ", studentNumber=" + studentNumber + "]";  
        }  
    }

    測試類

    import org.springframework.context.support.ClassPathXmlApplicationContext;  

    import com.spring.bean.FactoryBeanPojo;  

    /**  
     * @author  作者 wangbiao 
     * @parameter  
     * @return  
     */
      
    public class FactoryBeanTest {  
        public static void main(String[] args){  
            String url = "com/spring/config/BeanConfig.xml";  
            ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext(url);  
            Object school=  cpxa.getBean("factoryBeanPojo");  
            FactoryBeanPojo factoryBeanPojo= (FactoryBeanPojo) cpxa.getBean("&factoryBeanPojo");  
            System.out.println(school.getClass().getName());  
            System.out.println(factoryBeanPojo.getClass().getName());  
        }  
    }

    輸出的結(jié)果:

    十一月 162016 10:28:24 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh  
    INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1e8ee5c0: startup date [Wed Nov 16 10:28:24 CST 2016]; root of context hierarchy  
    十一月 162016 10:28:24 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions  
    INFO: Loading XML bean definitions from class path resource [com/spring/config/BeanConfig.xml]  
    十一月 162016 10:28:24 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons  
    INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@35b793ee: defining beans [student,school,factoryBeanPojo]; root of factory hierarchy  
    com.spring.bean.Student  
    com.spring.bean.FactoryBeanPojo

    從結(jié)果上可以看到當(dāng)從IOC容器中獲取FactoryBeanPojo對象的時候,用getBean(String BeanName)獲取的確是Student對象,可以看到在FactoryBeanPojo中的type屬性設(shè)置為student的時候,會在getObject()方法中返回Student對象。

    所以說從IOC容器獲取實現(xiàn)了FactoryBean的實現(xiàn)類時,返回的卻是實現(xiàn)類中的getObject方法返回的對象,要想獲取FactoryBean的實現(xiàn)類,得在getBean(String BeanName)中的BeanName之前加上&,寫成getBean(String &BeanName)。

    參考

    https://blog.csdn.net/wangbiao007/article/details/53183764
    https://blog.csdn.net/qiesheng/article/details/72875315
    https://www.cnblogs.com/redcool/p/6413461.html

    來源:cnblogs.com/aspirant/p/9082858.html


    最后,再給大家推薦我之前寫的10萬字Springboot經(jīng)典學(xué)習(xí)筆記,在Java開發(fā)寶典里回復(fù):筆記,即可領(lǐng)取。
    點贊是最大的支持 
    瀏覽 64
    點贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    台湾午夜无码 | 色九九色九九色九九 | a一级片网站 | 97国产成人无码精品久久久 | 偷拍自拍第一页 |