Java EE學習筆記(二)

Spring中的Bean

一、Bean的配置:

a)、Bean的本質就是Java中的類,而Spring中的Bean其實就是對實體類的引用,來生產Java類對象,從而實現生產和管理Bean 。java

b)、Spring容器支持兩種格式的配置文件:Properties文件和XML文件。在實際開發中,最常使用的是XML文件格式的配置方式,這種配置方式是經過XML文件來註冊並管理Bean之間的依賴關係。spring

c)、XML配置文件的根元素是<beans>,<beans>中包含了多個<bean>子元素,每個<bean>子元素定義了一個Bean,並描述了該Bean如何被裝配到Spring容器中。app

d)、關於<beans>元素的經常使用屬性以下表所示:ide

 e)、若是在Bean中未指定id和name,則Spring會將class值看成id使用。函數

二、Bean的實例化

實例化Bean有三種方式,分別爲構造器實例化、靜態工廠方式實例化和實例工廠方式實例化(其中最經常使用的是構造器實例化)。測試

 

1)、構造器實例化:指Spring容器經過Bean對應的類中默認的構造函數來實例化Bean。this

src->com.itheima.instance.constructorspa

①Bean1.javaprototype

1 package com.itheima.instance.constructor;
2 
3 public class Bean1 { // 實例化Bean1的對象時調用其無參構造方法 4     
5 }

②beans1.xml3d

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
4 xsi:schemaLocation="http://www.springframework.org/schema/beans 
5                       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
6    <bean id="bean1" class="com.itheima.instance.constructor.Bean1" />
7 </beans>

③測試類:InstanceTest1.java

 1 package com.itheima.instance.constructor;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 //構造器實例化Bean
 7 public class InstanceTest1 { 
 8     public static void main(String[] args) {
 9         // 一、定義配置文件路徑
10         String xmlPath = "com/itheima/instance/constructor/beans1.xml";
11         // 二、ApplicationContext在加載配置文件時,對Bean進行實例化(Spring容器會經過id爲bean1ID的實現類Bean1中默認的無參構造方法對Bean進行實例化)
12         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
13         // 三、經過容器獲取Bean1的實例
14         Bean1 bean = (Bean1) applicationContext.getBean("bean1ID");
15         System.out.println(bean);
16     }
17 }

④運行結果:

2)、靜態工廠:要求本身建立一個靜態工廠的方法來建立Bean的實例。

src->com.itheima.instance.static_factory

①Bean2.java

1 package com.itheima.instance.static_factory;
2 
3 public class Bean2 {
4     //無需添加任何方法
5 }

②MyBean2Factory.java

1 package com.itheima.instance.static_factory;
2 
3 public class MyBean2Factory { // 建立工廠類MyBean2Factory 4     // 使用本身的工廠建立Bean2實例(使用靜態方法建立Bean2實例)
5     public static Bean2 createBean() { 
6         return new Bean2();
7     }
8 }

③beans2.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 5                       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
 6      
 7      <bean id="bean2ID" class="com.itheima.instance.static_factory.MyBean2Factory" 
 8     factory-method="createBean" />
 9     <!-- 因爲使用的是靜態工廠方法,因此須要經過class屬性指定其對應的工廠實現類爲MyBean2Factory 
10         factory-method屬性來告訴Spring容器,須要createBean這個工廠方法
11     -->
12 </beans>

④測試類:InstanceTest2.java

 1 package com.itheima.instance.static_factory;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 // 靜態工廠實例化Bean
 7 public class InstanceTest2 {
 8     public static void main(String[] args) {
 9         String xmlPath = "com/itheima/instance/static_factory/beans2.xml";
10         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
11         System.out.println(applicationContext.getBean("bean2ID"));
12     }
13 }

⑤運行結果:

3)、實例工廠:採用直接建立Bean實例的方式,在配置文件中,經過factory-bean屬性配置一個實例工廠,而後使用factory-method屬性肯定使用工廠中的哪一個方法

src->com.itheima.instance.factory

①Bean3.java

1 package com.itheima.instance.factory;
2 
3 public class Bean3 {
4     //無需添加任何方法
5 }

②MyBean3Factory.java

 1 package com.itheima.instance.factory;
 2 
 3 public class MyBean3Factory { // 建立工廠類MyBean3Factory
 4     public MyBean3Factory() { // 默認使用無參構造方法輸出語句
 5         System.out.println("bean3工廠實例化中");
 6     }
 7     // 建立Bean3實例的方法
 8     public Bean3 createBean() {
 9         return new Bean3();
10     }
11 }

③beans3.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 5                       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
 6     <!-- 配置工廠 -->
 7       <bean id="myBean3FactoryID" class="com.itheima.instance.factory.MyBean3Factory" />
 8      <!-- 使用factory-bean屬性指向配置的實例工廠 (myBean3FactoryID),該屬性值就是工廠Bean的id。
 9          使用factory-method屬性肯定使用工廠中的哪一個方法 (createBean)
10      -->
11      <bean id="bean3ID" factory-bean="myBean3FactoryID" factory-method="createBean" />
12 </beans>

④測試類:InstanceTest3.java

 1 package com.itheima.instance.factory;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class InstanceTest3 {
 7     public static void main(String[] args) {
 8         String xmlPath = "com/itheima/instance/factory/beans3.xml";
 9         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
10         System.out.println(applicationContext.getBean("bean3ID"));
11     }
12 }

⑤運行結果:

三、Bean的做用域:

1)、做用域的種類

Spring 4.3中爲Bean的實例定義了7種做用域,以下表所示: 

在上表7種做用域中,singleton和prototype是最經常使用的兩種做用域。

2)、singleton做用域

a)、singleton是Spring容器默認的做用域,當Bean的做用域爲singleton時,Spring容器就只會存在一個共享的Bean實例。singleton做用域對於無會話狀態的Bean(如Dao 組件、Service組件)來講,是最理想的選擇。

b)、在Spring配置文件中,可使用<bean>元素的scope屬性,將Bean的做用域定義成singleton。例如:

<bean id="scope" class="com.itheima.scope.Scope" scope="singleton"/>

c)、src->com.itheima.scope

①Scope.java

1 package com.itheima.scope;
2 
3 public class Scope {
4     //無需寫任何方法
5 }

②beans4.xml

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
4 xsi:schemaLocation="http://www.springframework.org/schema/beans 
5                       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
6     <bean id="scopeID" class="com.itheima.scope.Scope" scope="singleton"/> 
7 </beans>

③測試類:ScopeTest.java

 1 package com.itheima.scope;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class ScopeTest {
 7     public static void main(String[] args) {
 8         String xmlPath = "com/itheima/scope/beans4.xml";
 9         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
10         // 輸出得到實例
11         System.out.println(applicationContext.getBean("scopeID"));
12         System.out.println(applicationContext.getBean("scopeID")); 
13         // 兩次輸出結果相同,這說明Spring容器只建立了一個Scope類的實例
14     }
15 }

④運行結果:

3)、prototype做用域

a)、對須要保持會話狀態的Bean(如Struts 2的Action類)應該使用prototype做用域。在使用prototype做用域時,Spring容器會爲每一個對該Bean的請求都建立一個新的實例

b)、在Spring配置文件中,一樣使用<bean>元素的scope屬性,將Bean的做用域定義成prototype 。例如:

<bean id="scope" class="com.itheima.scope.Scope" scope=" prototype "/>

c)、src->com.itheima.scope

①beans4.xml

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
4 xsi:schemaLocation="http://www.springframework.org/schema/beans 
5                       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
6     <!--<bean id="scopeID" class="com.itheima.scope.Scope" scope="singleton"/> -->
7       <bean id="scopeID" class="com.itheima.scope.Scope" scope="prototype"/> 
8       <!-- 在singleton做用域下,只建立一個Bean實例,而在prototype做用域下,每次建立不一樣的Bean實例 -->
9 </beans>

②運行結果:

四、Bean的生命週期

1)、Spring容器能夠管理Bean部分做用域的生命週期。

2)、Spring容器中Bean的生命週期流程以下圖所示:

五、Bean的裝配方式

Bean的裝配能夠理解爲依賴關係注入Bean的裝配方式Bean依賴注入的方式。Spring容器支持多種形式的Bean的裝配方式,如基於XML的裝配、基於註解(Annotation)的裝配和自動裝配(其中最經常使用的是基於註解的裝配)。

1)、基於XML的裝配

a)、2種方式:設值注入(Setter Injection)和構造注入(Constructor Injection)。

b)、設值注入要求一個bean必須知足2點要求:Bean類必須有一個默認的無參構造方法、Bean類必須爲須要注入的屬性提供對應的setter方法

c)、使用設值注入時,在Spring配置文件中,須要使用<bean>元素的子元素<property>來爲每一個屬性注入值;

d)、構造注入要求Bean類必須提供有參構造方法,配置文件中,須要使用<bean>元素的子元素<constructor-arg>來定義構造方法的參數,可使用value屬性(或子元素)來設置該參數的值。

src->com.itheima.assemble

①User.java

 1 package com.itheima.assemble;
 2 import java.util.List;
 3 
 4 import javax.swing.plaf.basic.BasicInternalFrameTitlePane.SystemMenuBar;
 5 
 6 public class User {
 7     private String username;
 8     private Integer password;
 9     private List<String> list;
10     /*
11      * 一、使用構造注入
12      * 1.一、提供帶全部參數的有參構造方法
13      */
14     public User (String username, Integer passward, List<String> list) { // 有參構造方法
15         super(); // 調用父類的無參構造方法,能夠不寫
16         this.username = username;
17         this.password = passward;
18         this.list = list;
19     }
20     
21     /*    
22      * 二、使用設值注入
23      * 2.一、提供默認無參構造方法
24      * 2.二、爲全部屬性提供setter方法
25      */
26     public User() { // 無參構造方法
27         super(); // 調用父類Object的無參構造方法,能夠不寫
28     }
29     public void setUsername(String username) {
30         this.username = username;
31     }
32     public void setPassword(Integer password) {
33         this.password = password;
34     }
35     public void setList(List<String> list) {
36         this.list = list;
37     }
38     
39     @Override
40     public String toString() { // 重寫父類的Object的toString方法
41         return "User [username=" + username + ", password=" + password + ", list=" + list + "]";
42     }
43 }

②beans5.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 5                       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
 6     <!-- 一、使用構造注入方式裝配User實例 -->
 7       <bean id = "user1ID" class = "com.itheima.assemble.User">
 8       <!-- 
 9         <constructor-arg> 元素用於定義構造方法的參數,
10         其index表示其索引(從0開始),value屬性用於設置注入的值,
11           其子元素<list>來爲User類中對應的list集合屬性注入值。 
12       -->
13       <constructor-arg index = "0" value = "tom" />
14       <constructor-arg index = "1" value = "123456" />
15       <constructor-arg index = "2" >
16              <list>
17                  <value>"constructorvalue1"</value>
18                  <value>"constructorvalue2"</value>
19           </list>
20       </constructor-arg>
21       </bean>
22       
23       <!-- 使用設值注入方式裝配User實例 -->
24     <bean id = "user2ID" class = "com.itheima.assemble.User">
25     <!-- 
26           <property>元素用於調用Bean實例中的setter方法完成屬性的賦值,從而完成依賴注入,
27           而其子元素<list>一樣是爲User類中對應的list集合屬性注入值。
28     -->
29         <property name="username" value = "張三"></property>
30           <property name="password" value = "654321"></property>
31           <!-- 注入list集合 -->
32           <property name="list">
33                <list>
34                    <value>"setlistvalue1"</value>
35                    <value>"setlistvalue2"</value>
36                   </list>    
37           </property>
38       </bean>
39 </beans>

③測試類:XmlBeanAssembleTest.java

 1 package com.itheima.assemble;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class XmlBeanAssembleTest {
 7     public static void main(String[] args) {
 8         String xmlPath = "com/itheima/assemble/beans5.xml";
 9         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
10         System.out.println(applicationContext.getBean("user1ID"));
11         System.out.println(applicationContext.getBean("user2ID"));
12     }
13 }

④運行結果:

2)、基於Annotation的裝配

a)、基於XML的裝配可能會致使XML配置文件過於臃腫,給後續的維護和升級帶來必定的困難。爲此,Spring提供了對Annotation(註解)技術的全面支持。

b)、src->com.itheima.annotation

①UserDao.java

1 package com.itheima.annotation;
2 
3 public interface UserDao {
4     public void save();
5 }

②UserDaoImpl.java

 1 package com.itheima.annotation;
 2 import org.springframework.stereotype.Repository;
 3 
 4 @Repository("userDaoID") 
 5 // @Repository註解將UserDaoImpl(數據訪問層DAO層)的類標識爲Spring中的Bean,其寫法至關於配置文件中
 6 // <bean id = "userDaoID" class = "com.itheima.annotation.UserDaoImpl" />的編寫
 7 public class UserDaoImpl implements UserDao{ 
 8     public void save() {
 9         System.out.println("userdaoID...save...");
10     }
11 }

③UserService.java

1 package com.itheima.annotation;
2 
3 public interface UserService {
4     public void save();
5 }

④UserServiceImpl.java

 1 package com.itheima.annotation;
 2 
 3 import javax.annotation.Resource;
 4 import org.springframework.stereotype.Service;
 5 
 6 @Service("userServiceID")
 7 // @Service註解將(業務層的)UserServiceImpl類標識爲Spring中的Bean,至關於配置文件中
 8 // <bean id = "userServiceID" class = "com.itheima.annotation.UserServiceImpl" />的編寫
 9 
10 public class UserServiceImpl implements UserService{
11     @Resource(name = "userDaoID")
12     /*    
13      * @Resource註解標註在UserDao的Bean的實例上,至關於配置文件中
14      * <property name = "userDao" ref = "userDaoID" />的編寫
15      * @Resource默認按照Bean實例名稱進行裝配,2個屬性:name屬性解析爲Bean實例名稱;type屬性解析爲Bean實例類型
16      * 若是都不指定,匹配過程爲實例名稱->實例類型,若都不匹配,則拋出NoSuchBeanDefinitionException異常
17     */
18     private UserDao userDao;
19     
20     public void save() {
21         // 調用成員對象userDao中的save方法
22         this.userDao.save();
23         System.out.println("userServiceID...save...");    
24     }
25 }

⑤UserController.java

 1 package com.itheima.annotation;
 2 
 3 import javax.annotation.Resource;
 4 import org.springframework.stereotype.Controller;
 5 
 6 @Controller("userControllerID")
 7 //@Controller註解標註了UserController類,這至關於配置文件中
 8 //<bean id = "userControllerID" class = "com.itheima.annotation.UserController" />的編寫
 9 
10 public class UserController {
11     @Resource(name = "userServiceID")
12     // @Resource註解標註在UserService的Bean的實例上,至關於配置文件中
13     // <property name = "userService" ref = "userServiceID" />的編寫
14     private UserService userService;
15     
16     public void save() {
17         this.userService.save();
18         System.out.println("userControllerID...save...");
19     }
20 }

⑥beans6.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4 xmlns:context="http://www.springframework.org/schema/context"
 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 6                     http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 7                     http://www.springframework.org/schema/context 
 8                     http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 9      <!-- 以上補充context的約束信息,使用 context 命名空間 ,
10          經過配置<context:annotation-config />來開啓註解處理器 -->
11      <!--分別定義3個Bean實例,這裏再也不須要配置子元素<property>完成setter方法依賴注入  -->
12         
13          <context:annotation-config />
14          <bean id="userDaoID" class="com.itheima.annotation.UserDaoImpl" />
15          <bean id="userServiceID" class="com.itheima.annotation.UserServiceImpl" />
16          <bean id="userControllerID" class="com.itheima.annotation.UserController" /> 
17 </beans>

⑦AnnotationAssembleTest.java

 1 package com.itheima.annotation;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 //基於Annotation(註解)的裝配
 7 public class AnnotationAssembleTest { 
 8     public static void main(String[] args) {
 9         String xmlPath = "com/itheima/annotation/beans6.xml";
10         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
11         // 獲取UserController的Bean實例userControllerID
12         UserController userController = (UserController) applicationContext.getBean("userControllerID");
13         userController.save();
14     }
15 }

⑧運行結果:

c)、除了能夠像示例中經過<bean>元素來配置Bean外,還能夠經過包掃描的形式來配置一個包下的全部Bean:

<context:component-scan base-package="Bean所在的包路徑" />

d)、將beans6.xml文件中的13~16行代碼替換成下面這個,運行效果同樣。

<!-- Spring註解提供了另一種高效的註解配置方式,(對包路徑下的全部Bean文件進行掃描) -->
    <!--使用 context 命名空間 ,通知Spring掃描指定包下全部Bean類,進行註解解析 -->   
        <context:component-scan base-package="com.itheima.annotation" />

3)、自動裝配

a)、所謂自動裝配就是將一個Bean自動的注入到到其餘Bean的Property中(也就是類成員變量賦值)。 Spring的<bean>元素中包含一個autowire屬性,咱們能夠經過設置autowire的屬性值來自動裝配Bean。

b)、autowire屬性有5個值,其值及說明下表所示:

c)、修改UserServiceImple.java和UserController.java,分別增長類屬性的setter方法;修改Spring配置文件,使用autowire屬性配置Bean;其餘文件不用修改。

①UserServiceImple.java

 1 package com.itheima.annotation;
 2 
 3 import javax.annotation.Resource;
 4 import org.springframework.stereotype.Service;
 5 
 6 @Service("userServiceID")
 7 // @Service註解將(業務層的)UserServiceImpl類標識爲Spring中的Bean,至關於配置文件中
 8 // <bean id = "userServiceID" class = "com.itheima.annotation.UserServiceImpl" />的編寫
 9 
10 public class UserServiceImpl implements UserService{
11     @Resource(name = "userDaoID")
12     /*    
13      * @Resource註解標註在UserDao的Bean的實例上,至關於配置文件中
14      * <property name = "userDao" ref = "userDaoID" />的編寫
15      * @Resource默認按照Bean實例名稱進行裝配,2個屬性:name屬性解析爲Bean實例名稱;type屬性解析爲Bean實例類型
16      * 若是都不指定,匹配過程爲實例名稱->實例類型,若都不匹配,則拋出NoSuchBeanDefinitionException異常
17     */
18     private UserDao userDao;
19     
20     // 添加類屬性UserDao的setter方法
21     public void setUserDao(UserDao userDao) {
22         this.userDao = userDao;
23     }
24     
25     public void save() {
26         // 調用成員對象userDao中的save方法
27         this.userDao.save();
28         System.out.println("userServiceID...save...");    
29     }
30 }

②UserController.java

 1 package com.itheima.annotation;
 2 
 3 import javax.annotation.Resource;
 4 import org.springframework.stereotype.Controller;
 5 
 6 @Controller("userControllerID")
 7 //@Controller註解標註了UserController類,這至關於配置文件中
 8 //<bean id = "userControllerID" class = "com.itheima.annotation.UserController" />的編寫
 9 
10 public class UserController {
11     @Resource(name = "userServiceID")
12     // @Resource註解標註在UserService的Bean的實例上,至關於配置文件中
13     // <property name = "userService" ref = "userServiceID" />的編寫
14     private UserService userService;
15     
16     // 添加類屬性UserService的setter方法
17     public void setUserService(UserService userService) {
18         this.userService = userService;
19     }
20     
21     public void save() {
22         this.userService.save();
23         System.out.println("userControllerID...save...");
24     }
25 }

③beans6.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4 xmlns:context="http://www.springframework.org/schema/context"
 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 6                     http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 7                     http://www.springframework.org/schema/context 
 8                     http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 9     
10     <!-- 使用bean元素的autowire屬性完成自動裝配,所謂自動裝配,就是將一個Bean自動地注入到其餘Bean的Property中 -->
11     
12     <!-- 注意:這裏的id(除了最後一個)名稱應對應setter方法中的參數(實例化對象),即設置了autowire以後,
13         Spring會自動尋找userService Bean中的屬性,並將屬性名稱與配置文件中定義的Bean作匹配,
14         不然會報java.lang.NullPointerException異常。
15      -->
16     <bean id="userDao" class="com.itheima.annotation.UserDaoImpl" />
17     <bean id="userService" class="com.itheima.annotation.UserServiceImpl" autowire="byName" />
18     <bean id="userControllerID" class="com.itheima.annotation.UserController" autowire="byName"/>
19     
20 </beans>

④運行結果:

相關文章
相關標籤/搜索