Spring4.3.8學習[二]

如果轉(zhuǎn)載文章請注明出處, 謝謝 !
本系列文章是學習完 Spring4.3.8 后的詳細整理, 如果有錯誤請向我指明, 我會及時更正~??

Spring4.3.8

Spring4.3.8學習[一]

3.4 依賴注入(DI)

控制反轉(zhuǎn),我們可以把它看作是一個概念。而依賴注入(Dependency Injection)是控制反轉(zhuǎn)的一種實現(xiàn)方法.
James Shore給出了依賴注入的定義:依賴注入就是將實例變量傳入到一個對象中去(Dependency injection means giving an object its instance variables)。

3.4.1 xml 形式

3.4.1.1 使用構(gòu)造器注入

通過參數(shù)順序, 類型等

<bean id="person" class="com.lanou.domain.Person">
    <!--根據(jù)參數(shù)名稱注入-->
    <constructor-arg name="name" value="大老王"/>
    <!--根據(jù)索引index注入-->
    <constructor-arg index="1" value="24"/>
    <!--根據(jù)構(gòu)造器參數(shù)的類型-->
    <constructor-arg type="java.lang.String" value="men"/>
</bean>

3.4.1.2 使用屬性 setter 方法

public class Person {
    private String name;
    private int age;
    private String gender;
    private Car car;
    private List list;
    private Set set;
    private Map map;
    private Properties properties;
    private Object[] objects;
     [屬性 setter 方法]
}

簡單Bean的注入

<bean name="person" class="com.lanou.domain.Person">
    <!-- property 就是一個bean 的屬性
        name 用來描述屬性的名稱
        value 就是屬性值, 一般類型(基本類型和 String)
    -->
    <property name="name" value="狗蛋兒"/>
    <property name="age" value="22"/>
    <property name="gender" value="men"/>
</bean>

引用其他Bean

<bean name="car" class="com.lanou.domain.Car"></bean>
<bean name="person" class="com.lanou.domain.Person">
    <!--spring 容器內(nèi)部創(chuàng)建的car 對象給 Person 的 car屬性賦值-->
    <property name="car" ref="car"/>
</bean>

3.4.1.3 裝配 list 集合

<property name="list">
    <list>
        <value>list1</value>
        <ref bean="car"/>
    </list>
</property>

3.4.1.4 裝配 set

<property name="set">
    <set>
        <value>set1</value>
        <ref bean="car"/>
    </set>
</property>

3.4.1.5 裝配 map

<property name="map">
    <map>
        <entry key="m1">
            <value>map1</value>
        </entry>
        <entry key="m2">
            <ref bean="car"/>
        </entry>
    </map>
</property>

3.4.1.5 裝配 properties

<property name="properties">
    <props>
        <prop key="p1">pp1</prop>
        <prop key="p2">pp2</prop>
    </props>
</property>

3.4.1.6 裝配 Object[]

<property name="objects">
    <list>
        <value>obj1</value>
        <ref bean="car"/>
    </list>
</property>

3.4.2 注解 Annotation

注解的注入會在XML之前,因此后者配置將會覆蓋前者.

配置bean

3.4.2.1 @Component

@Component是所有受 Spring 管理組件的通用形式,泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。
@Component 不推薦使用。

@Component
public class Person {
}

3.4.2.2@Controller

@Controller對應表現(xiàn)層的Bean,也就是Action, 例:

@Controller
@Scope("prototype")
public class UserAction {
}

3.4.2.3 @Respository

用于標注數(shù)據(jù)訪問組件,即DAO組件

@Repository
public class UserDao {
} 

3.4.2.4 @Service

用于標注業(yè)務層組件

@Service
public class UserServiceImpl {
}


對于掃描到的組件, Spring有默認的命名策略 :
1)使用非限定類名,第一個字母小寫
(UserServiceImpl -> userServiceImpl)

2)在注解中通過 value 屬性值標識組件的名稱
(通??梢詫serServiceImpl -> userService,可以將Impl拿掉,這是一個習慣)

@Service("userService")
public class UserServiceImpl {
}

(3)當在組件類上使用了特定的注解之后, 還需要在 Spring 的配置文件中聲明 <context:component-scan>
base-package 屬性指定一個需要掃描的基類包,Spring 容器將會掃描這個基類包里及其子包中的所有類.
當需要掃描多個包時, 可以使用逗號分隔.

配置 bean 的屬性

3.4.2.5 @Autowired

使用@Autowired 注解自動裝配, @Autowired 默認按類型裝配.

可以在普通setter方法上使用@Autowired注解

public class UserServiceImpl implements UserService{
    private UserDao userDao;

    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

可以將注解應用到構(gòu)造器和字段上

public class UserServiceImpl implements UserService{
    private UserDao userDao;

    @Autowired
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
}
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDao userDao;
}

可以將注解應用到任意名稱或參數(shù)的方法上

public class UserServiceImpl implements UserService{
    private UserCatalog userCatalog;
    private UserDao userDao;
    
    @Autowired
    public void prepare(UserCatalog catalog, UserDao dao){
        this.userCatalog = catalog;
        this.userDao = dao;
    }

可以把指定類型的所有Bean提供給一個數(shù)組類型, 集合類型的變量

public class UserServiceImpl implements UserService{
    @Autowired
    private UserCatalog[] catalogs;
}

xml 中只定義了幾個 對應bean

<bean id="userService" class="com.lanou.service.impl.UserServiceImpl"/>
<bean id="dao" class="com.lanou.dao.impl.UserDaoImpl"/>
<bean id="catalog" class="com.lanou.domain.UserCatalog"/>

@Autowired注解是按類型裝配依賴對象,默認情況下它要求依賴對象必須存在,一旦找不到對應的Bean,自動注入就會失敗。若要改變默認的策略或允許null值,可以設置它required屬性為false。

public class UserServiceImpl implements UserService{
      // xml 中沒有定義UserFinder的 bean
    @Autowired(required = false)
    private UserFinder userFinder;
}

3.4.2.6 @Qualifier

使用@Qualifier調(diào)整基于注解的自動注入.
在指定參數(shù)上使用@Qualifier,可以縮小類型匹配的范圍,更容易為參數(shù)找到指定的Bean。
[想使用按名稱裝配,可以結(jié)合@Qualifier注解一起使用]

public class UserServiceImpl implements UserService{
    @Qualifier("userD")
    @Autowired
    private UserDao userD;
}

對應的Bean定義如下所示。
標識值為“userDe”的Bean將會被標記為@Qualifier(“userDe”)的參數(shù)所注入:

<bean id="dao" class="com.lanou.dao.impl.UserDaoImpl">
    <qualifier value="userD"/>
</bean>

如果全部使用注解, 可以在UserDaoImpl中使用Repository配置

@Repository("userDe")
public class UserDaoImpl implements UserDao{
}

3.4.2.7 @Resource

@Resource 注解和@Autowired一樣,也可以標注在字段或?qū)傩缘膕etter方法上.

@Resource注解默認按名稱裝配。

名稱可以通過@Resource的name屬性指定,如果沒有指定name屬性,
當注解標注在字段上,即默認取字段的名稱作為bean名稱尋找依賴對象;
當注解標注在屬性的setter方法上,即默認取屬性名作為bean名稱尋找依賴對象。

public class UserServiceImpl implements UserService{
    @Qualifier("userD")
    @Autowired
    private UserDao userD;

    @Resource(name = "daoU")
    private UserDao userDao;
}

注: 如果沒有指定name屬性,并且按照默認的名稱找不到依賴對象時, @Resource注解會回退到按類型裝配。但一旦指定了name屬性,就只能按名稱裝配了。

3.4.2.8 @Required

@Required注解應用于Bean屬性的setter方法,如下:

public class UserServiceImpl implements UserService{
    private UserDao userDao;
    @Required
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

這個表明Bean的屬性值必須在配置中指定,可以通過顯示的在Bean定義中指定,也可以使用自動注入。若沒有為這個屬性指定值,那么容器會拋出一個異常。

<bean id="userService" class="com.lanou.service.impl.UserServiceImpl">
    <property name="userDao" ref="dao"/>
</bean>
<bean id="dao" class="com.lanou.dao.impl.UserDaoImpl"/>

3.4.2.8 @PostConstruct & @PreDestroy

生命周期注解
之前的做法是在xml中定義init-method 和 destroy-method方法

public class User {
    public User() {
        System.out.println("user .. 構(gòu)造函數(shù)");
    }
    @PostConstruct
    public void  init(){
        System.out.println("I'm  init  method  using  @PostConstrut....");
    }

    @PreDestroy
    public void  destroy(){
        System.out.println("I'm  destory method  using  @PreDestroy.....");
    }
}

3.5 掃描

spring2.5為我們引入了組件自動掃描機制,它可以在類路徑底下尋找標注了@Component、@Service、@Controller、@Repository注解的類,并把這些類納入進spring容器中管理.

它的作用和在xml文件中使用bean節(jié)點配置組件是一樣的。要使用自動掃描機制,我們需要打開以下配置信息:

  1. 引入context命名空間 需要在xml配置文件中配置以下信息
  2. 在配置文件中添加context:component-scan標簽
<?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">
        
    <!-- 自動掃描指定包及其子包下的所有Bean類 -->
    <context:component-scan base-package="com.lanou.domain"/>

在 base-package 指明一個包, 表明自動掃描目錄 com.lanou 包及其子包中的注解,當需要掃描多個包時, 可以使用逗號分隔.
其他用法:

<!-- 通過resource-pattern指定掃描的資源 -->
 <!--只掃描repository下的類-->
<context:component-scan base-package="com.lanou" resource-pattern="dao/*.class"></context:component-scan>

<!-- 不掃描repository注解的類 ??梢耘渲枚鄠€。-->
<context:component-scan base-package="com.lanou" >
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

<!--  只掃描repository注解的類。可以配置多個。  -->
<context:component-scan base-package="com.lanou"  use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

<!--  不掃描某個接口。可以配置多個。使用assignable類型   -->
<context:component-scan base-package="com.lanou"  use-default-filters="true">
    <context:exclude-filter type="assignable" expression="com.lanou.dao.UserDao"/>
</context:component-scan>

<!--  只掃描某個接口。 -->
<context:component-scan base-package="com.lanou"  use-default-filters="false">
    <context:include-filter type="assignable" expression="com.lanou.dao.UserDao"/>
</context:component-scan>

3.6 Spring 的繼承

public class People {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}


public class Student extends People {

}
<bean name="people" class="com.lanou.domain.People">
    <property name="name" value="111"/>
</bean>
<bean name="student" class="com.lanou.domain.Student"></bean>
public void testExtents(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    Student student = (Student) context.getBean("student");
// student 打印出來的名字為 null  
 System.out.println(student.getName());
}

配置文件需要更改

<!-- parent 實現(xiàn)了 spring 容器內(nèi)部的繼承關(guān)系 
       在父類中進行賦值, 子類繼承父類內(nèi)容
-->
<bean name="people" class="com.lanou.domain.People">
    <property name="name" value="111"/>
</bean>
<bean name="student" class="com.lanou.domain.Student" parent="people"></bean>

還有其他方式解決 student 的名字賦值問題么?
student 也繼承了 people 的 name setter 方法

Spring4.3.8學習[三]
Spring4.3.8學習之 與 Struts2 整合[四]
Spring4.3.8學習之與Hibernate4 整合[五]
Spring4.3.8學習之S2SH 整合[六]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容