Spring IOC丶依賴注入

1. Spring IOC

1.1 概述

  • 把實體的創建權交給Spring,以便解耦,Spring使用配置文件+實例工廠+反射創建實例

1.2 配置文件applicationContext.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.xsd">

	<!-- id:實例的名稱,可以被配置文件和Spring創建實例時引用 -->
	<!-- class:被實例化的類完整路徑 -->
	<!-- scope:實例的作用範圍
			singleton:單例,該類只會創建一次對象,默認值(常用)
			prototype:多例,每次從容器中獲取Bean時,都會創建一個新的實例,Acition實例化需要多例(常用)
			request:用於Web應用環境,針對每次HTTP請求都會創建一個實例
			session:用於Web應用環境,同一個會話共享同一個實例,不同的會話使用不同的實例
			global session:僅在Portlet的Web應用中使用,同一個全局會話共享一個實例,對於非Portlet環境,等同於session
	-->
	<bean id="student" class="com.domain.Student" scope="singleton"></bean>	

<!-- 在一個配置文件中引入多個配置文件(配置文件拆分) -->
<import resource="/applicationContext2.xml"/>	
</beans>

1.3 從Spring容器中獲取實例

//讀取spring配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext("/applicationContext.xml");
//根據bean標籤的id屬性值查找實例
Student student= ac.getBean("student",Student.class);
//操作實例對象
System.out.println(student.toString());

2. 依賴注入

2.1 構造方法注入屬性值

<bean id="student" class="com.domain.Student">
	<!-- Student類中定義了構造方法Student(Integer id, String name) -->
	<!-- constructor-arg表示構造方法的參數,name表示參數名稱,value表示參數值 -->
	<constructor-arg name="id" value="1"></constructor-arg>
	<constructor-arg name="name" value="張三"></constructor-arg>
</bean>

2.2 setter方法注入屬性值

<bean id="grade" class="com.domain.Grade">
	<!-- property標籤表示一個屬性,name表示屬性名,value表示要注入的屬性值 -->
	<property name="id" value="1"></property>
	<property name="name" value="高一(1)班"></property>
</bean>

<bean id="student" class="com.domain.Student">
	<!-- ref可以注入對象類型的數據,ref的值對應上面id爲grade的bean -->		
	<property name="grade" ref="grade"></property>
</bean>

2.3 p命名空間注入屬性值

  • Spring2.5後才能使用p命名空間
  • 需要在beans標籤下引入p命名空間規範
    xmlns:p="http://www.springframework.org/schema/p"
<!-- 直接在bean標籤的屬性中使用p命名空間爲對的屬性賦值 -->
   <!-- 基本類型格式:【p:對象屬性名="值"】 -->
   <!-- 對象引用格式:【P:對象屬性名-ref="值"】 --> 
<bean id="grade" class="com.domain.Grade" p:id="2" p:name="高一(4)班"></bean>
<bean id="student" class="com.domain.Student" p:grade-ref="grade"></bean>

2.4 SpEL注入屬性值

  • Spring3後才能使用SpEL
  • SpEL能執行java代碼(跟EL表達式類似)
<bean id="grade" class="com.domain.Grade">
	<!-- SpEL表達式格式:   #{值}    值爲字符串需要加單引號 -->		
	<property name="id" value="#{3}"></property>
	<property name="name" value="#{'高三(3)班'}"></property>
</bean>

<bean id="student" class="com.domain.Student">	
	<!-- 無論值是否爲對象類型,直接用value即可,SpEL會自動解析值類型 -->		
	<property name="grade" value="#{grade}"></property>
	<!-- SpEL可以執行java代碼 -->
	<property name="name" value="#{grade.getName()+'的學生'}"></property>
</bean>

2.5 自動裝配autowire

  • 2.5.1 自動裝配autowire屬性值
    • byName

      • 根據屬性名自動裝配,
      • BeanFactory查找id與屬性的setter方法匹配的Bean,找到即自動注入,否則什麼都不做
    • byType 根據屬性類型自動裝配

      • 如果正好有一個與依賴屬性類型相同的Bean,就自動裝配這個屬性
      • 如果有多個這樣的的Bean,Spring無法決定哪個Bean,就拋出一個致命異常
      • 如果沒有匹配的Bean,就什麼都不做,屬性不會被設置
    • no

      • 不使用自動裝配
    • constructor

      • 跟byType差不多,它是應用於構造注入自動裝配
      • 如果在容器中沒有找到與構造器參數類型一致的Bean,那麼將會拋出異常
<bean id="userDao" class="com.dao.impl.UserDaoImpl" ></bean>	
<bean id="productDao" class="com.dao.impl.ProductDaoImpl"></bean>

<!-- ShoppingCarServiceImpl中需要用到userDao和productDao,autowire能自動給這兩個屬性值(需要setter方法)自動裝配賦值 -->
<bean id="shoppingCarService" class="com.service.impl.ShoppingCarServiceImpl" autowire="byName"></bean>
  • 全局自動裝配
    • Spring配置文件設置了default-autowire後當前文件的bean都會默認自動裝配,如果是拆分多個配置文件,只有設置了default-autowire的配置文件才生效,其他配置文件不生效
 <!-- 在Spring配置文件開頭的<beans>文件中添加default-autowire="自動裝配值" -->
<beans default-autowire="byName" >

2.6 注入不同類型的數據(瞭解)

  • 注入基本類型(字符串和其他基本類型)

    • 看上面例子
  • 引用bean實例

    • 看上面例子
  • 使用內部Bean

<bean id="userBiz" class="com.biz.impl.UserBizImpl">
	 <property name="userDao">
	     <!-- 內部bean直接使用class屬性,不用id屬性,不能被其他bean調用 -->
	     <bean class="com.dao.impl.UserDaoImpl"></bean>
	 </property>
</bean>
  • 注入List集合或數組類型的屬性值
<bean id="user" class="com.entity.User">
	  <property name="hobbies">
	      <!-- list標籤注入List集合或數組的多個值 -->
	      <list>
	          <value>籃球</value>
	          <value>足球</value>
	          <value>乒乓球</value>
	      </list>
	  </property>
</bean>
  • 注入Set集合的屬性值
<bean id="user" class="com.entity.User">
	<property name="hobbies">
	    <!-- set標籤注入Set集合 -->
	    <set>
	        <value>籃球</value>
	        <value>足球</value>
	        <value>乒乓球</value>
	    </set>
	</property>
</bean>
  • 注入Map集合的屬性值
<bean id="user" class="com.entity.User">
   <property name="hobbies">
        <!-- map標籤注入Map集合多個鍵值對 -->
        <map>
            <!-- 一個entry標籤表示一個鍵值對 -->
            <entry>
                <!-- entry標籤的子key標籤表示Map集合的key,key標籤包含的value表示key值 -->
                <key><value>basketball</value></key>
                <!-- entry標籤的子value標籤表示Map集合的value -->
                <value>籃球</value>
            </entry>
            <entry>
                <key><value>football</value></key>
                <value>足球</value>
            </entry>
        </map>
    </property>
</bean>
  • 注入Properties類型的屬性值
<bean id="user" class="com.entity.User">
	<property name="hobbies">
	    <!-- props標籤注入Properties集合多個鍵值對 -->
	    <props>
	        <!-- 一個prop標籤表示一個鍵值對 -->
	        <!-- key屬性表示key值 -->
	        <!-- prop標籤包含的文本是value值 -->
	        <prop key="backetball">籃球</prop>
	        <prop key="football">足球</prop>
	    </props>
	</property>
</bean>
  • 注入null和空字符串值
<!-- value標籤中間不填東西就是空字符串 -->
<property name="a"><value></value></property>
<!-- null標籤表示null值 -->
<property name="b"><null/></property>

3. 使用註解方式依賴注入

3.1 修改配置文件

  • 標籤多了個xmlns:context項,xsi:schemaLocation的值多了2個
  • 設置掃描註解類的包
  • default-autowire設置和context:component-scan是在同一個配置文件,則會對類的對象屬性進行自動裝配(對象屬性需要要setter方法,不需要在對象屬性上添加註解)
<?xml version="1.0" encoding="UTF-8"?>
<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" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

	
	<!-- 註解組件掃描,base-package表示要掃描的包,多個包用逗號隔開 -->
	<context:component-scan base-package="com.service.impl,com.dao.impl"></context:component-scan>
</beans>

3.2 常用註解

  • 3.2.1 註解定義bean
    • @Repository("bean id") 用於標註Dao的實現類
@Repository("productDao")
public class ProductDaoImpl implements ProductDao {}
  • @Service("bean id") 用於標註Service實現類
@Service("shoppingCarService")
public class ShoppingCarServiceImpl implements ShoppingCarService {}
  • @Controller("bean id") 用於標註控制器類
  • @Component("bean id") 用於標註通用bean的類
  • 3.2.2 自動裝配註解
    • 註解自動裝配不用setter方法,直接在屬性上面添加註解即可
    • @Autowired 根據類型進行自動裝配
    • @Qualifier("bean id") 與@Autowired結合一起使用就變成根據名字進行自動裝配
    • @Resource(name="bean id") 根據名字進行自動裝配,等同於上面兩個結合
//@Autowired與@Qualifier結合一起就是按名字自動裝配
@Autowired 
@Qualifier("userDao")
private UserDao userDao;

//根據名字進行自動裝配
@Resource(name="productDao")
private ProductDao productDao;
  • 3.2.3 基本類型數據註解
@Value("我是註解方式的屬性值")
private String message;
  • 3.2.4 bean作用域註解
    @Scope("作用域") 在類上面註解作用範圍,作用域的值參考2.5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章