一個類中,儘量不和其它的類產生耦合(即不使用new)的方法:1) 使用工廠模式。直接從工廠中得到實例;
2) 控制反轉(IOC)。應用本身不負責依賴對象的創建和維護,由外部容器負責。控制權利由應用轉移到了外部容器,控制權的轉移就是所謂反轉;依賴注入(DI)。在運行期間,由外部容器動態地將依賴對象注入到組件中。
面向切面編程(AOP):通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的技術。主要功能:日誌記錄、性能統計、安全控制、事務處理、異常處理等。使用JDK的動態代理可以實現AOP。
Spring的IOC容器包含並管理應用對象的配置和生命週期。可以配置每個bean如何被創建,可以配置每個bean是隻有一個實例,還是每次需要時都生成一個新的實例,以及它們是如何相互關聯的。
Spring的優點:1) 降低組件之間的耦合度,實現解耦;
2) 容器提供單例模式支持;
3) AOP技術;
4) 持久化服務;
5) 對主流的框架提供了集成支持。
BeanFactory和ApplicationContext
區別:a) ApplicationContext是BeanFactory的子接口;
b) ApplicationContext的功能要多於BeanFactory,如它可以加載外部的資源文件、可以自動進行AOP切面、可以識別自動代理的的類、可以識別用於監聽Bean創建的類等。
ApplicationContext是一個接口,有多個實現類,我們在使用時就是用的他的某個實現類:a) ClassPathXmlApplicationContext(讀取類路徑中的資源)
b) FileSystemXmlApplicationContext(讀取指定路徑的資源,推薦使用絕對路徑)
c) XmlWebApplicationContext(在Web應用中使用)
使用類ApplicationContext獲取Bean:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"cn/itcast/b_springhelloworld/applicationContext.xml"); //獲取配置文件
UserServiceImpl userServiceImpl = (UserServiceImpl) applicationContext.getBean(
"userService"); //從配置文件中獲得對象
實例化bean的三種方式
a) 使用類構造器實例化
b) 使用靜態工廠方法實例化
工廠類:
public class StaticDaoFactory {
// 方法必須聲明爲static的
public static Object createUserDaoInstance() {
System.out.println("StaticDaoFactory.createUserDaoInstance()");
return new UserDaoImpl();
}
}
c) 使用實例化的工廠對象中的方法實例化(首先創建工廠bean,再調用工廠中創建實例的方法得到實例對象)
工廠類:
public class SimpleDaoFactory {
// 方法不能聲明爲static的
public static Object createUserDaoInstance() {
System.out.println("SimpleDaoFactory.createUserDaoInstance()");
return new UserDaoImpl();
}
}
a) singleton(單例,默認值);餓漢式(默認值,加載類時就初始化實例),懶漢式(lazy-init=”true”,第一次調用getInstance()時獲取bean時才生成實例)。對所有bean應用延遲初始化,在根節點beans中設置屬性default-lazy-init=”true”;
b) prototype(原型,每次獲取的都是新對象);
c) 其他作用域。
依賴注入的配置方式
一、通過setter方法注入:
二、通過構造器注入:
或是:
注入普通屬性(基本類型或者String類型):
注入null值
3.3.2依賴對象的注入
方式一:
定義bean時不分先後,Spring會自動處理他們之間的依賴關係,以決定先創建誰。
方式二:使用內部bean,因爲沒有id或name,所以該bean不能被其他bean使用
3.3.3注入集合屬性
一、創建類
public class User {
private String name;
// 集合屬性要定義爲接口類型
// 集合類型可以不初始化,因爲會注入一個新的集合對象
// 集合最好指定強類型,以便Spring轉型,如果未指定,就會是String型的值
// 如果沒有指定強類型,也可以在配置時指定:
// 10
private Set addressSet = new HashSet();
private Set numberSet;
private List addressList;
private String[] addressArray;
private Map addressCodeMap;
private Properties userProperties;
public void printInfo() {
System.out.println("name = " + name);
System.out.println("addressSet = " + addressSet);
System.out.println("numberSet = " + numberSet);
System.out.println("addressList = " + addressList);
System.out.println("addressArray = " + Arrays.toString(addressArray));
System.out.println("addressCodeMap = " + addressCodeMap);
System.out.println("userProperties = " + userProperties);
}
// getter與setter略
}
二、配置
上地東路27號上地東路28號12上地東路27號上地東路28號helloworld
依賴注入的註解方式
a) 引入context命名空間;
b) 在配置文件中添加context:component-scan標籤。
xmlns:context="http://www.springframework.org/schema/context"
<!-- 設置爲自動掃描與裝配bean,掃描指定包及其所有下級包中的類,可以寫多個,之間用英文的逗號隔開 -->
<context:component-scan base-package="cn.itcast"></context:component-scan>
組件自動掃描機制,它可以在類路徑底下尋找標註了@Component、@Service、@Controller、@Repository註解的類,並把這些類納入進spring容器中管理。它的作用和在xml文件中使用bean節點配置組件是一樣的。
功能介紹:
@Service用於標註業務層組件
@Controller用於標註控制層組件(如struts中的action)
@Repository用於標註數據訪問組件,即DAO組件
@Component泛指組件,當組件不好歸類的時候,我們可以使用這個註解進行標註
@Scope用於指定當前bean的作用域
@Resource默認按名稱裝配,當找不到與名稱匹配的bean纔會按類型裝配。如果沒有指定name屬性,並且按照默認的名稱找不到依賴對象時, @Resource註解會回退到按類型裝配。但一旦指定了name屬性,就只能按名稱裝配了。
@Resource是用於注入依賴的bean:
可以通過name屬性指定所需要的bean的名稱,如果找不着,則拋異常。或可以通過type屬性指定所需要的bean的類型,如果只有一個bean匹配這個類型,則就是他它
@Resource(name="personDao")
private PersonDao personDao;;//用於字段上
@Resource(name="personDao")
public void setPersonDao(PersonDao personDao) {//用於屬性的set方法上
this.personDao = personDao;
}
後一種相當於xml配置文件中的
<property name=“personDao" ref="personDao" />
在applicationContext.xml中配置bean時,可以指定abstract屬性,其默認爲false,如果爲true,則容器就不會創建這個類的實例,這時就可以不指定class屬性。通常用於抽取公共的配置到一個不對應具體類的bean定義,此bean只用於被其他bean定義繼承。
在聲明bean時可以指定parent屬性,其值爲另一個bean的id或是name的值,表示把parent中的定義繼承過來,就像自己有這些定義一樣。注意:這只是在配置時方便,與實際的類結構無關。在父Bean中定義的屬性必須要在子Bean中出現。如果子Bean中沒有定義相關屬性,將會導致容器初始化失敗。
引入外部資源
classpath:cn/itcast/l_di_placeholder/a.propertiesclasspath:cn/itcast/l_di_placeholder/b.properties
二、使用加載外部的資源文件
要使用Context命名空間
a) 先找properties中的配置,如果找到就返回;
b) 如果第一步沒找到,就從system proeprties中查找(使用System.getProperty(String key) 的值),如果找到就返回;
c) 如果還沒找到,就拋異常,說找不到這個變量的值。