下文:SpringIOC 二—— 容器 和 Bean的深刻理解html
這篇文章去年寫的,緣起於去年某段時間被領導臨時「抓壯丁」般的叫過去作java開發,而後在網上找了一個 SpringMVC 的 demo,學習一下,而後依葫蘆畫瓢,開始了本身的項目開發,也還順利完成了任務。在使用 SpringMVC 的過程當中,我被這個被稱做「最優秀」的 java 框架 —— Spring 深深地吸引了,那些曾經掌握的多種設計模式的思想在其中都有實現,好比工廠模式、單例模式、觀察者模式等等,因而在工做之餘認真地學習了這個框架。
學習新東西老是使人興奮的,然而大多數學過的知識很容易又會忘記,因此便想整理一下,寫點筆記,方便本身之後複習查看。java
部分參考資料:
《Spring實戰(第4版)》
《輕量級 JavaEE 企業應用實戰(第四版)》
Spring 官方文檔
W3CSchool Spring教程
易百教程 Spring教程web
Spring是一個開源框架,Spring是於2003年興起的一個輕量級的Java開發框架,由Rod Johnson在其著做Expert One-On-One J2EE Development and Design中闡述的部分理念和原型衍生而來。它是爲了解決企業應用開發的複雜性而建立的。框架的主要優點之一就是其分層架構,分層架構容許使用者選擇使用哪個組件。Spring提供了約20多個組件,開發者能夠根據本身須要選擇組件。Spring的核心是控制反轉(IoC)和麪向切面編程(AOP)spring
從最簡單的 Hello,Spring 例子來體會一下使用 Spring 框架。首先看看不使用 Spring 框架的代碼:
HelloSpring.java 類:express
package com.sharpcj; public class HelloSpring { private String name; public void sayHello() { System.out.println("Hello," + name + "!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Test.java 類:編程
package com.sharpcj; public class Test { public static void main(String[] args) { HelloSpring hs = new HelloSpring(); hs.setName("Spring"); hs.sayHello(); } }
輸出結果:設計模式
Hello,Spring!
下面咱們用 Spring 框架來實現這個例子。
Spring 框架官方下載地址: http://repo.springsource.org/libs-release-local/
Spring 框架阿里雲下載地址:http://maven.aliyun.com/nexus/content/groups/public/springframework/緩存
添加從 Spring 框架核心 JAR 文件:tomcat
這裏只是使用Spring的基本功能,因此須要使用到下面的這幾個Jar包:
安全
這裏我使用的 idea,用 gradle 編譯的(用 maven 過程相似)。爲了提升下載速度,我使用了阿里雲的 maven 倉庫,而後添加依賴,最新穩定版本是 5.0.6 , build.gradle
文件部分截圖:
代碼更改以下:
HelloSpring.java 類
package com.sharpcj; public class HelloSpring { private String name; public void sayHello() { System.out.println("Hello," + name + "!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Test.java 類
package com.sharpcj; import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext context = new FileSystemXmlApplicationContext("src/beans.xml"); HelloSpring hs = context.getBean("helloSpring", HelloSpring.class); hs.sayHello(); } }
此時在 src 目錄下新建了一個文件 beans.xml
:
<?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-3.0.xsd"> <bean id="helloSpring" class="com.sharpcj.HelloSpring"> <property name="name" value="Spring"/> </bean> </beans>
此時運行 Test.java 的 main 方法,打印結果以下:
Hello,Spring!
這樣咱們就用 Spring 框架實現了最簡單的 Hello Spring 程序。
上面用 Spring 框架實現的代碼中,咱們在 Test.java 類中,並無經過 「new HelloSpring()」 這樣的調用 Spring 構造方法去建立 HelloSpring 的對象,而是使用 Spring 核心容器建立的。
第一步是咱們使用框架 API FileSystemXmlApplicationContext() 來建立應用程序的上下文。這個 API 加載 beans 的配置文件並最終基於所提供的 API,它處理建立並初始化全部的對象,即在配置文件中提到的 beans。
第二步是使用已建立的上下文的 getBean() 方法來得到所需的 bean。這個方法使用 bean 的 ID 返回一個最終能夠轉換爲實際對象的通用對象。一旦有了對象,你就可使用這個對象調用任何類的方法。能經過這種方式建立的對象,必定是在 beans.xml 文件中配置的。
Spring 核心容器就好像是一個超級大的工廠,在配置文件中配置過的對象都會被當成 Spring 容器管理的對象。Spring 把容器中的一切對象統稱爲 Bean 。 Spring 中的 Bean 與傳統的 java Bean 不一樣,對 Spring 而言,任何一個 java 類,均可以當成是 Bean 來處理。
仍是用上面 HelloSpring 的例子,該例子實在過於簡單,只有一個 bean, 沒有涉及到兩個 bean 之間的依賴關係,不過仍是能夠用它來理解Spring容器裝配Bean的三種裝配方式。爲了說明依賴注入的場景,舉個其它例子:
人用筆寫字。僞代碼以下:
Pen 類:
public class Pen { // property 暫不關心 }
Person 類:
public class Person { private Pen pen; public Person(Pen pen) { this.pen = pen; } public Pen getPen() { return this.pen; } public void setPen(Pen pen) { this.pen = pen; } // 這裏咱們暫不關心該方法 public void write() { } }
下面對於這種依賴關係,將分別用僞代碼來講明構造注入和設置注入。
上面例子便是,再也不贅述。
若是存在多個Bean, 之間有依賴關係:
構造注入:
<?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-3.0.xsd"> <bean id="pen" class="com.sharpcj.Pen"> </bean> <bean id="person" class="com.sharpcj.Person"> <constructor-arg name = "pen", ref = "pen"> </bean> </beans>
設值注入:
<?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-3.0.xsd"> <bean id="pen" class="com.sharpcj.Pen"> </bean> <bean id="person" class="com.sharpcj.Person"> <property name = "pen", ref = "pen"> </bean> </beans>
com.sharpcj.HelloSpring.java
代碼以下:
package com.sharpcj; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class HelloSpring { private String name; public void sayHello() { System.out.println("Hello," + name + "!"); } public String getName() { return name; } @Value("Spring") public void setName(String name) { this.name = name; } }
建立類 com.sharpcj.HelloConfig.java
用來開啓組件掃描:
package com.sharpcj; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan public class HelloConfig { }
修改com.sharpcj.Test.java
package com.sharpcj; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(com.sharpcj.HelloConfig.class); HelloSpring hello = context.getBean("helloSpring", HelloSpring.class); hello.sayHello(); } }
@Component
註解的類即爲 Bean 。 @Configuration
註解的即爲配置文件,@ComponentScan
註解表示開啓自動掃描,默認掃描該配置類所在的包,若是掃描其它包,多個包,形式以下:
@Configuration @ComponentScan(basePackageClasses = {com.a.A.class, com.b.B.class})
也能夠每一個包內配置以後,再配置一個總的配置文件:
@Configuration @Import({com.a.AConfig.class, com.b.BConfig.class}) public class TotalConfig { }
若是存在多個Bean, 之間有依賴關係:
// pen 類:
@Component public class Pen { // property 暫不關心 }
構造注入:
@Component public class Person { private Pen pen; @Autowired public Person(Pen pen) { this.pen = pen; } public Pen getPen() { return this.pen; } public void setPen(Pen pen) { this.pen = pen; } // 這裏咱們暫不關心該方法 public void write() { } }
設值注入:
@Component public class Person { private Pen pen; public Pen getPen() { return this.pen; } @Autowired public void setPen(Pen pen) { this.pen = pen; } // 這裏咱們暫不關心該方法 public void write() { } }
此時 java 類無需使用註解。
一樣建立一個類,com.sharpcj.HelloConfig.java
來進行裝配 Bean。
package com.sharpcj; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HelloConfig { @Bean public HelloSpring helloSpring(){ return new HelloSpring(); } }
被 @Bean 標註的方法返回的即爲惟一 Bean(默認單例模式),方法名隨便取。
Test:
ApplicationContext context=new AnnotationConfigApplicationContext(com.sharpcj.HelloConfig.class); Person person = context.getBean(Person.class); person.write();
若是存在多個Bean, 之間有依賴關係:
構造注入:
@Configuration public class PConfig { @Bean public GPen hehe() { return new GPen(); } @Bean public QPen haha() { return new QPen(); } @Bean public Person xixi() { Person person = new Person(hehe()); return person; } }
設值注入:
@Configuration public class PConfig { @Bean public GPen hehe() { return new GPen(); } @Bean public QPen haha() { return new QPen(); } @Bean public Person xixi() { Person person = new Person(); person.setPen(hehe()); return person; } }
這篇文章記錄了Spring容器和Bean的概念,Spring 的基本使用,以及Spring容器裝配Bean的三種方式。關於Spring 容器的知識點比較多,下篇文章接着寫點 Spring 容器裝配 Bean 的高級知識點。