Spring容器以及springioc原理介紹

這篇文章為大家?guī)碛嘘P(guān)Spring容器以及spring ioc原理的介紹。文章不僅介紹Spring容器以及spring ioc原理的知識點(diǎn),還介紹了Spring的配置和使用,希望大家通過這篇文章能有所收獲。

網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序設(shè)計(jì)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了伊川免費(fèi)建站歡迎大家使用!

一:spring ioc的原理:

小A剛到公司老大安排了一個(gè)活,公司前不久剛開發(fā)了一個(gè)社交網(wǎng)站,運(yùn)行不太穩(wěn)定,經(jīng)常會出現(xiàn)莫名其妙的bug,需要在必要的地方加上日志,方便找到錯(cuò)誤,小A很快就開發(fā)好了日志記錄類,為了以后的擴(kuò)展性,還添加了一個(gè)接口:


public interfaceILogger {
   voiddoLog();
}

 

public classConsolLoggerimplementsILogger {
   @Override
   public voiddoLog() {
        System.out.println("打印日志到控制臺");
    }
}

先在添加好友功能這里增加一個(gè)日志:

public classFriend {
   private ILoggerlogger=new ConsoleLogger ();
   public voidaddFriend(){
        System.out.println("添加好友!");
       logger.doLog();//添加日志
   
}
}

發(fā)現(xiàn)好多地方需要添加的,一個(gè)一個(gè)加上去,三天后終于全部加好了。

這天老大又找到了小A:小A啊,現(xiàn)在日志是在控制臺打印的,你看能不能保存在文件里面啊。小A皺了皺眉,先估算了一下工作量,需要先開發(fā)一個(gè)保存日志到文件的類,然后逐個(gè)修改,工作量有點(diǎn)大哦,而且都是重復(fù)性的工作,太沒挑戰(zhàn),萬一以后還需要再改那豈不是又要浪費(fèi)幾天美好時(shí)光,有沒有簡單點(diǎn)的辦法呢?

工廠模式,小A突然靈光一閃,對就是它了,先寫一個(gè)記錄日志到文件的類:

public classFileLoggerimplementsILogger{
   public voiddoLog(){
        System.out.println("記錄日志到文件");
    }
}

再寫一個(gè)工廠類:

public class LoggerFactory {
    

    public static ILogger createLogger(){
        return new FileLogger();
    }
}

現(xiàn)在可以通過工廠創(chuàng)建日志對象了:

public class Friend {

    

    private FileLogger logger = LoggerFactory.createLogger();
    public void addFriend(){
        System.out.println("添加好友!");
        logger.doLog();//添加日志
    
}
}

以后再有需求變動的時(shí)候只需要修改工廠類就可以了,完美,等等似乎還有一點(diǎn)瑕疵,如果能夠?qū)崿F(xiàn)連工廠類都不需要修改豈不是更完美,有點(diǎn)得寸進(jìn)尺了哦,人類的智慧是無限的看步驟:

1.    將日志的實(shí)現(xiàn)類的全限定名放到配置文件中

<bean id  = “myLogger” class=”cn.xh.logger.FileLogger”>

2.    通過xml解析根據(jù)id從配置文件中讀出日志的實(shí)現(xiàn)類的全限定名

3.    通過反射動態(tài)創(chuàng)建日志實(shí)現(xiàn)類的對象

修改以后的工廠類偽代碼如下:

public class LoggerFactory {

    public static ILogger createLogger(String id){

//解析xml根據(jù)id獲取要?jiǎng)?chuàng)建的日志類的全限定名

//使用反射動態(tài)創(chuàng)建日志實(shí)現(xiàn)類對象

//將該對象返回
        return;
    }
}

如果需要修改日志類,現(xiàn)在只需要修改xml配置文件就可以了,完美。

這就是spring ioc實(shí)現(xiàn)的基本原理,當(dāng)然身為一個(gè)偉大的產(chǎn)品,怎么可以如此簡單呢.


二.Spring容器

在Spring中有一個(gè)核心概念叫容器,顧名思意,容器是用來裝東西的,裝的什么東西呢?就是需要管理的對象,裝在哪里呢?一個(gè)HashMap中, 大致的可以理解為以對象名為鍵,以對象本身為值的一個(gè)HashMap,當(dāng)然遠(yuǎn)比這要復(fù)雜。

我們用容器來實(shí)例化對象,管理對象之間的依賴。

在spring中有兩個(gè)重要的接口:BeanFactory和ApplicationContext,所謂的容器就是實(shí)現(xiàn)了BeanFactory接口或者BeanFactory接口的類的實(shí)例,BeanFactory是最頂層最基本的接口,它描述了容器需要實(shí)現(xiàn)的最基本的功能,比如對象的注冊,獲取。

public interfaceBeanFactory {
    StringFACTORY_BEAN_PREFIX="&";
   /*
     *四個(gè)不同形式的getBean方法,獲取實(shí)例
     */
   
Object getBean(String name)throwsBeansException;
    <T>TgetBean(String name, Class<T> requiredType)throwsBeansException;
    <T>TgetBean(Class<T> requiredType)throwsBeansException;
    Object getBean(String name, Object... args)throwsBeansException;
   //是否存在
   
booleancontainsBean(String name);
   //是否為單實(shí)例
   
booleanisSingleton(String name)throwsNoSuchBeanDefinitionException;
   //是否為多例
   
booleanisPrototype(String name)throwsNoSuchBeanDefinitionException;//
    //名稱、類型是否匹配
   
booleanisTypeMatch(String name, Class<?> targetType)
           throwsNoSuchBeanDefinitionException;
   //獲取類型
   
Class<?> getType(String name)throwsNoSuchBeanDefinitionException;
   //根據(jù)實(shí)例的名字獲取實(shí)例的別名
   
String[] getAliases(String name);
}

 

ApplicationContext依賴BeanFactory接口,它描述的內(nèi)容更加廣泛,例如資源的獲取等等。

當(dāng)然除了這兩個(gè)接口還有很多其它接口,這里不重點(diǎn)討論,附上一張圖以作了解。

Spring容器以及spring ioc原理介紹

通常我們使用的最多的容器是實(shí)現(xiàn)了ApplicationContext接口的類,ClassPathXmlApplicationContext和FileSystemXmlApplicationContext

ClassPathXmlApplicationContext在類路徑下尋找配置文件來實(shí)例化容器,默認(rèn)是讀取 src 目錄下的配置文件

FileSystemXmlApplicationContext在文件系統(tǒng)路徑下尋找配置文件來實(shí)例化容器,默認(rèn)是讀取項(xiàng)目名下一級,與src同級的配置文件

這里的配置文件是xml文件,它描述了被管理的對象和對象之間的依賴(beans.xml)。

<beansxmlns="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"
>
    <beanid="userDao"class="cn.xh.dao.UserDaoImpl"></bean>
</beans>

在這個(gè)配置文件中有一行配置:

<beanid="userDao"class="cn.xh.dao.UserDaoImpl"></bean>

表示使用spring容器管理的對象UserDaoImpl

加載配置文件創(chuàng)建容器:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");

獲取容器中的對象

UserDaoImpl userDao = (UserDaoImpl) applicationContext.getBean("userDao");

 我們來比較一下beanFactory和applicationContext:

1.BeanFactory接口定義了容器的最基本功能,它可以讀取類的配置文檔,管理類的加載,實(shí)例化,維護(hù)類之間的依賴關(guān)系。實(shí)現(xiàn)它的容器實(shí)例化時(shí)并不會初始化配置文件中定義的類,初始化動作發(fā)生在第一次調(diào)用時(shí)。 第一次調(diào)用創(chuàng)建好對象后就放入緩存中以后使用直接從緩存中獲取。

2. applicationContext接口除了提供容器的基本功能外還提供了很多的擴(kuò)展功能,實(shí)現(xiàn)它的容器實(shí)例化時(shí)就會將配置文件中定義的類初始化。

3.最常用的的容器是實(shí)現(xiàn)了applicationContext接口的容器ClassPathXmlApplicationContext和FileSystemXmlApplicationContext

  

三.spring ioc的注入方式。

 spring依賴注入(DI),是spring 控制反轉(zhuǎn)(IOC)的具體實(shí)現(xiàn),在一個(gè)類A中需要一個(gè)成員變量B,以前是直接給B賦值,現(xiàn)在通過Spring容器在需要的時(shí)候?qū)的值注入到A對象中,簡單的說,就是通過spring在適當(dāng)?shù)臅r(shí)候給A的成員變量B賦值。

Spring的注入有三種方式:構(gòu)造方法注入,setter方法注入,接口注入,使用最廣泛的是setter方法注入,接口注入的方式現(xiàn)在已經(jīng)很少用了。我們重點(diǎn)介紹前面兩種注入方式:

構(gòu)造方法注入:

就是使用類中的構(gòu)造函數(shù),給成員變量賦值,注意這里是使用spring框架來為我們賦值,上代碼,創(chuàng)建一個(gè)Person類,通過構(gòu)造方法為其成員變量賦值。

 

public classPerson {
   private intpid;
   privateStringpname;
   private intage;
   publicPerson(intpid, String pname,intage) {
       this.pid= pid;
       this.pname= pname;
       this.age= age;
    }
   @Override
   publicString toString() {
       return"Person{"+
               "pid="+pid+
               ", pname='"+pname+'\''+
               ", age="+age+
               '}';
    }
}

spring的配置:

<beanid="person"class="cn.xh.dao.Person">
    <constructor-argname="pid"value="1"></constructor-arg>
    <constructor-argname="pname"value="張三"></constructor-arg>
    <constructor-argname="age"value="18"></constructor-arg>
</bean>

 

通過<constructor-argname="pid"value="1"></constructor-arg>給Person的成員變量賦值。

構(gòu)造方法注入有它的局限性,試想一下如果有20個(gè)成員變量,構(gòu)造方法的參數(shù)豈不是要20個(gè),很不優(yōu)雅,使用setter方法注入可以解決這個(gè)問題。

Setter方法注入

在一個(gè)類中我們往往會通過get和set方法來對成員變量進(jìn)行賦值和取值的操作,可以通過set方法來給成員變量賦值。

public classPerson {
   private intpid;
   privateStringpname;
   private intage;

   public intgetPid() {
       returnpid;
    }

   public voidsetPid(intpid) {
       this.pid= pid;
    }

   publicString getPname() {
       returnpname;
    }

   public voidsetPname(String pname) {
       this.pname= pname;
    }

   public intgetAge() {
       returnage;
    }

   public voidsetAge(intage) {
       this.age= age;
    }

   @Override
   publicString toString() {
       return"Person{"+
               "pid="+pid+
               ", pname='"+pname+'\''+
               ", age="+age+
               '}';
    }
}

spring的配置:

<beanid="person"class="cn.xh.dao.Person">
    <propertyname="pid"value="1"></property>
    <propertyname="pname"value="張三"></property>
    <propertyname="age"value="18"></property>
</bean>

配置<propertyname="pid"value="1"></property>以后可以通過類提供的set方法將值賦給成員變量。

使用setter方法注入有一個(gè)需要特別注意的地方,假如我們給Person類加一個(gè)有參的構(gòu)造函數(shù):

public classPerson {
   private intpid;
   privateStringpname;
   private intage;

   publicPerson(intpid, String pname,intage) {
       this.pid= pid;
       this.pname= pname;
       this.age= age;
    }

}

程序運(yùn)行的時(shí)候會報(bào)錯(cuò),原因就是當(dāng)我們加上有參構(gòu)造函數(shù)以后就不會默認(rèn)生成無參構(gòu)造函數(shù),使用setter方法注入容器啟動的時(shí)候會調(diào)用無參構(gòu)造函數(shù)去實(shí)例化對象,所以我們需要手動加上無參構(gòu)造函數(shù)。

 看完上述內(nèi)容,你們對Spring容器以及spring ioc原理有進(jìn)一步的了解嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀。

文章標(biāo)題:Spring容器以及springioc原理介紹
標(biāo)題來源:http://muchs.cn/article28/igedcp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、Google、服務(wù)器托管、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、網(wǎng)站導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)