天天看點

spring-ioc應用

IOC(Inversion of Control)控制反轉, 将對在自身對象中的一個内置對象的控制權反轉。所謂的反轉,即把内置對象的控制權反轉給一個容器,而應用程式隻需要提供對象的類型即可。是面向對象程式設計中的一種設計原則,可以用來減低計算機代碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI),還有一種方式叫“依賴查找”(Dependency Lookup)

IOC是一種需要達到的目标,DI和DL是實作的手段。他們之間的關系就像ORM(關系映射)和mybatis的關系一樣。

spring實作IOC的思路是提供一些配置資訊(注解和xml檔案)用來描述類之間的依賴關系,然後由容器去解析這些配置資訊,繼而維護好對象之間的依賴關系,前提是對象之間的依賴關系必須在類中定義好,比如A.class中有一個B.class的屬性,那麼我們可以了解為A依賴了B。既然我們在類中已經定義了他們之間的依賴關系那麼為什麼還需要在配置檔案中去描述和定義呢?

spring實作IOC的思路大緻可以拆分成3點應用程式中提供類,

1. 提供依賴關系(屬性或者構造方法)

2. 把需要交給容器管理的對象通過配置資訊告訴容器(xml、annotation,javaconfig)

3. 把各個類之間的依賴關系通過配置資訊告訴容器,和1豈不是重複,顯得多餘??自動裝配時是把第三部省略,這樣就不會顯得多餘。 完全使用xml就不能省略此步驟。

spring程式設計的風格

1. schemal-based-------xml

2. annotation-based-----annotation

3. java-based Container Configuration----java Configuration

spring注入的方式:

1. Constructor-based Dependency Injection 構造方法

<bean name="dao" class="dao.IndexDaoImpl"></bean>

<bean name="indexServiceImpl" class="service.IndexServiceImpl">
    <property name="dao" ref="dao" />
</bean>
           

或者屬性還可以寫成這樣

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                                   xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans     https://www.springframework.org/schema/beans/spring-beans.xsd"> 

<bean name="dao" class="dao.IndexDaoImpl"></bean>

<bean id="indexServiceImpl" class="service.IndexServiceImpl"
        p:dao="dao" /> 
</beans>
           
2. Setter-based Dependency Injection      setter方法
           
<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 
    https://www.springframework.org/schema/beans/spring-beans.xsd"> 

<!-- traditional declaration with optional argument names -->
<bean id="indexServiceImpl" class="service.IndexServiceImpl"/>
     <constructor-arg name="dao" ref="dao"/>
</bean> 

<bean name="dao" class="dao.IndexDaoImpl"></bean>
</beans>
           

或者使用c:dao

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          
    xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="indexServiceImpl" class="service.IndexServiceImpl"
    c:dao-ref="dao"/>
</bean>

<bean name="dao" class="dao.IndexDaoImpl"></bean>
</beans>
           

使用javaConifg技術:

開啟掃描中預設開啟了注解,是以不再需要額外去開啟注解

開啟注解可以使用@ComponentScan

<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com"/>
           

使用javaConifg技術:

由此有了第三種方式javaconfig,在某一個類上使用@Configuration和@ComponentScan注解就可以替代xml檔案(如果需要和xml檔案一起使用,還需要添加@ImportResource将xml檔案引入),此時,容器本身不再是通過加載xml檔案獲得,而是加載注解類。new ClassPathXmlApplicationContext(*.xml) 變為使用new AnnotationConfigApplicationContext(注解類.class),前者不具備解析自動解析注解的功能,是以需要在xml檔案中顯示注明包掃描範圍(開啟了注解),後者能自動解析注解。

自動裝配

上面說過,IOC的注入有兩個地方需要提供依賴關系,一是類的定義中,二是在spring的配置中需要去描述。自動裝配則把第二個取消了,即我們僅僅需要在類中提供依賴,繼而把對象交給容器管理即可完成注入。

在實際開發中,描述類之間的依賴關系通常是大篇幅的,如果使用自動裝配則省去了很多配置,并且如果對象的依賴發生更新我們可以不需要去更新配置,但是也帶來了一定的缺點

自動裝配的優點參考文檔:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-autowire

缺點參考文檔:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-autowired-exceptions

作為我來講,我覺得以上缺點都不是缺點

自動裝配的方法

no:

byName:使用此裝配類型時,如果bean的name屬性未指定,則預設和id屬性一緻。Spring容器根據xml檔案中name的值,去比對setXxx()方法去掉set且将X變為小寫x後的xxx值,然後将其注入,并不是根據屬性名去注入。在xml使用byName的作用和@Resource注解的功能一樣,隻不過@Resource是根據屬性名去注入,而不是setter()方法。如果@Resource指定了name屬性則根據byName,預設也是byName;若指定了type屬性,則根據byType屬性去注入。

@Resource根據byName時,預設是類名的首字母小寫後的類名。當然,我們也可以自定義,重寫自己的命名規則。一般我們也可以給類的注解@Component,@Controller等注解指定name屬性,達到重命名的效果。

byType:使用此裝配類型時,在面向接口程式設計時,如果該接口有多個實作類而且都交給了spring容器去管理,那麼程式啟動将報錯。另外在xml檔案中使用byType的作用和@AutoWired注解功能一樣,使用@AutoWired會首先根據

byType去查找,找不到或者查找有多個則根據byName(屬性名,而不是setter方法)去找,如果仍然找不到或是還有多個則會報錯。@AutoWired和@Qualifier一起使用的效果等同于byName裝配。

constructor:

@Component注解可以修飾@Controller,@Service, @Repository修飾的類,隻不過為了區分更清楚,而不建議這麼做。

自動裝配的方式參考文檔:

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-autowire

全局指定自動裝配類型,如下,一般不會如此操作。

spring懶加載

官網已經解釋的非常清楚了:

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-lazy-init

值得提醒的是,如果你想為所有的對都實作懶加載可以使用官網的配置

springbean的作用域

文檔參考:

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-scopes

預設是singleton

xml定義方式

annotation的定義方式

Singleton Beans with Prototype-bean Dependencies

意思是在Singleton 當中引用了一個Prototype的bean的時候引發的問題

官網引導我們參考https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-method-injection

spring聲明周期的回調

參考文檔:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-lifecycle

1、Methods annotated with @PostConstruct, @PreDestroy。 前者在對象建立後調用(構造方法之後,和afterPropertiesSet類似),後者在銷毀前調用。

2、afterPropertiesSet() as defined by the InitializingBean callback interface 實作InitializingBean 接口,重寫它的afterPropertiesSet()方法,在初始化完成後會自動執行此方法。

3、A custom configured init() method,此方法需要在

4、實作DisposableBean接口,重寫它的destory()方法,則在容器銷毀時會執行此方法。或者在xml的也可以。

beanOne和manager不存在依賴關系,但是前者的初始化需要manager先初始化時,就可以使用depends-on

<bean id="beanOne" class="ExampleBean" depends-on="manager"/> 
<bean id="manager" class="ManagerBean" />
           

@Lazy使用此注解修飾的類和在xml中使用的的效果一樣,預設都是使用懶加載。

Spring與spring mvc整合時,需要将spring mvc的xml檔案排除,現在不用了,因為采用springboot了。

使用以下依賴,會讓所有java類建立一個索引,大大提高掃描的速度,提升性能。

<dependency> 
	<groupId>org.springframework</groupId> 
	<artifactId>spring-context-indexer</artifactId>
 	<version>5.2.0.RELEASE</version> 
	<optional>true</optional> 
</dependency>