天天看點

Spring深入學習(一)——SpringIoc的了解

SpringIoc的了解

1、概念:控制反轉(Inversion of Control),是面向對象程式設計中的一種設計原則,可以用來降低計算機代碼之間的耦合度。最常見的實作方式叫做依賴注入(Dependency Injection),還有一種方式叫“依賴查找”(Dependency lookup)。Ioc控制反轉是指将由我們控制的建立對象及擷取依賴對象,交給IOC容器控制,由容器幫我們建立對象并關注依賴對象,控制對外部資源的擷取。

2、使用Ioc的原因:在程式開發過程中,使用面向抽象程式設計,面向抽象程式設計會産生類的依賴,spring為我們提供了管理的容器,即Ioc。有了管理容器後,類的産生過程交給了容器,我們就不用關心對象的産生了。

3、Ioc實作的思路和方法:首先需要提供一些配置資訊用來描述類之間的關系,然後由容器去解析這些配置資訊,繼而維護好對象之間的依賴關系,前提是對象間的依賴關系必須在類中定義好。比如A.class中有一個B.class屬性,那麼可以了解為A依賴了B。

大緻可分為3點:①應用程式中提供類,提供依賴關系(屬性或構造方法)。②把需要交給容器管理的對象通過配置資訊告訴容器。③把各類之間的依賴關系通過配置資訊告訴容器。

4、spring的程式設計風格(可混合使用)

①schema-based XML方式

②Annotation-based 注解方式(需要結合xml方式或javaconfig方式使用,開啟和掃描注解)

③java-based javaconfig方式(使用時需要建立配置類@Configuration,可通過@ImportResource(xml檔案)來加入xml配置檔案)

注意:前兩種方式通過ClassPathXMLApplicationContext解析,javaconfig通過AnnotationConfigApplicationContext解析。

5、Spring對象注入方法

①Constructor-based DI 構造方法注入

②setter-based DI set方法注入

spring3以前還提供了接口注入,但是spring4以後已經不再使用。注意使用XML注入時的p空間注入(p:name)和c空間注入(c:name)。

6、自動裝配:隻需在類中定義對象的依賴關系,而不需要在spring中配置依賴關系,這就是通過自動裝配來實作。

自動裝配方法:

①no 不自動裝配,需要提供對象間依賴的配置(預設方法)

②byType 按類型裝配

③byName 按名稱裝配

④constructor 類似于byType ,但适用于構造函數參數,容器中不能有多個構造函數

XML方式:在< beans >标簽中加入default-autowire=類型,來指定自動裝配的方法,也可以對某個< bean >單獨指定自動裝配方法。需要注意的是按名稱裝配時,名稱與set方法的值關聯。

注解方式:使用@Autowired注解或@Resource注解。

@Autowired和@Resource差別:它們都可以用來自動裝配bean,都可以寫在字段上或setter方法上。@Autowired屬于spring,預設按類型裝配,如果沒有找到才會按名稱查找,預設是必須存在的,可以通過required屬性改為false,即可允許null值。指定按名稱裝配可以結合@Qualifier注解進行使用。@Resource屬于J2EE,預設按照名稱裝配,名稱可通過name屬性進行指定,如果沒指定name屬性,當注解寫在屬性上時,預設取屬性名進行查找,如果注解寫在setter方法上時,預設取setter方法中set後的值第一個字母小寫進行裝配。當找不到名稱比對的bean時,才會按照類型進行裝配。但name或type屬性一旦指定,必須按照對應值裝配,找不到則報錯。用名稱裝配速度更快。

7、spring懶加載

在第一次請求時,Ioc容器才執行個體化Bean,而不是在初始化時就建立。xml中全局設定為懶加載,即在< beans >标簽中增加屬性default-lazy-init=true;給某個bean設定為懶加載,則在< bean >标簽中增加屬性lazy-init=true。注解和javaconfig方式在對應類中加入@Lazy注解即可實作懶加載。

8、spring的Bean作用域

注解@Scope。

singlton 單例,每次通路都是同一個Bean對象(spring中預設)

prototype 原型,每次通路都是新的Bean對象

request

session

application

websocket

注意問題:

Singleton Beans with Prototype-bean Dependencies:在Singleton 當中引用了一個Prototype的bean,會造成Prototype作用域的bean也隻能使用一個bean對象。

解決方法:

①實作ApplicationContextAware接口,重寫setApplicationContext()方法擷取ApplicationContext對象,通過此對象getBean擷取Prototype作用域的bean。

②使用@Lookup(bean名)注解(在XML中可以使用< lookup-method >标簽)查找Prototype作用域的bean,這時就不需要自動裝配。

例:@Lookup(“dao”)

public abstract Dao getDao();

通過 getDao()即可擷取bean對象。

9、spring生命周期的回調

①Initialization callbacks 初始化回調

實作InitializingBean接口,重寫afterPropertiesSet方法,該方法會在對象建立後初始化時調用。

Destruction callbacks 銷毀回調

實作DisposableBean接口,重寫destroy()方法,該方法在對象銷毀時調用。

②Default Initialization and Destroy Methods 預設的初始化和銷毀方法

在XML配置中,增加< beans > 标簽的default-init-method=‘方法名’或default-init-destroy=‘方法名’屬性,在對應類中重寫方法名方法即可。

③@Postconstruct和@Predestroy注解,分别表示初始化時調用方法和銷毀時調用方法。

10、spring其他常用注解

①@ComponentScan:用于掃描檔案

②@Primary:在多個對象進行選擇時使用,當有多個資料源時,設為主源,spring在讀取時會優先選擇這個注解标記的類。如@Autowired裝配Bean時,有多個相同類型Bean,可以設定其中一個為主類,spring會使用此類進行裝配。

③@Profile:用于環境切換,在對應環境下生效。可以用于切換某個bean,也可以用于切換整個配置檔案。

例:

public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext
                = new AnnotationConfigApplicationContext();
        //切換到@Profile的環境
        annotationConfigApplicationContext.getEnvironment().setActiveProfiles("@Profile的名字");
        annotationConfigApplicationContext.register(AppConfig.class);
        annotationConfigApplicationContext.refresh();

        TestService service = annotationConfigApplicationContext.getBean(TestService.class);

        System.out.println(service.getName());

    }
           

④@Bean依賴,可以作為參數傳入到方法中

@Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        //或者直接使用方法引入
        //sqlSessionFactoryBean.setDataSource(dataSource());
        return sqlSessionFactoryBean;
    }

    @Bean
    public DataSource dataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setPassword("root");
        dataSource.setUsername("root");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3308/turtle?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC");
        return dataSource;
    }
           

⑤@Component是@Service,@Repository和@Controller的父類,後面的注解隻是将功能細分,友善查找管理。spring文檔上提示将來可能會增加另外的含義,是以我們使用時最好按功能使用不同注解。

⑥可以用java注解代替spring注解使用。如@Inject代替@Autowired;@Named代替@Component;@Singleton代替@Scope(“singleton”)等。但都有局限性,如下表(來自官方文檔)。

Spring深入學習(一)——SpringIoc的了解

11、自定義注解

注解:描述資料的資料。可以在編譯類加載、運作時被讀取。

分類:

内建注解,标準注解類型。如:@Override,@SuppressWarnings等

元注解,修飾注解的注解。如:@Target(用于指定注解可使用的位置),@Retention(用于标注注解存活時間的長短)等

自定義注解:自己定義的注解,通過關鍵字@interface實作。接口名即為注解名,接口中的方法即為注解中可加的屬性。

例:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {

    public String value() default "";

}

@Entity("student")
public class Student {
    private String id;
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
           

總結,初步了解了Ioc的原理及使用和spring的一些功能,為後面的源碼學習打基礎,一步步掌握spring。