程序的耦合
耦合:程序間的依賴關(guān)系
包括:類之間的依賴乘凸,方法之間的依賴
解耦:降低程序見的依賴關(guān)系
實(shí)際開發(fā)中,應(yīng)該做到編譯期不依賴,運(yùn)行時(shí)才依賴
解耦的思路:
第一步,使用反射來創(chuàng)建對(duì)象何陆,而避免使用new關(guān)鍵字
第二部,通過讀取配置文件來獲取要?jiǎng)?chuàng)建的對(duì)象全限定類名
//1.注冊驅(qū)動(dòng)
//DriverManager.registerDriver(new com.mysql.jabc.DriverI());依賴于jar包豹储,如果缺少則會(huì)在編譯期時(shí)就報(bào)錯(cuò)
Class.forName("com.mysql.jdbc.Driver");//一個(gè)字符串
//2.獲取連接
Connection conn=DriverManager.getConnection(url:"jdbc:mysql://localhost:3306");
//3.獲取操作數(shù)據(jù)庫的預(yù)處理對(duì)象
PreparedStatement pstm=conn.prepareStatement(sql:"select * from emp");
//4.執(zhí)行SQL贷盲,得到結(jié)果集
ResultSet rs=pstm.executeQuery();
//5.遍歷結(jié)果集
while(rs.nest()){
System.out.println(rs.getString(columnLabel:"enam"));
}
//6.釋放資源
rs.close();
pstm.close();
conn.close();
創(chuàng)建Bean對(duì)象的工廠
Bean:在計(jì)算機(jī)英語中,有可重用組件的含義剥扣。
JavaBean:用Java語言編寫的可重用組件巩剖。
JavaBean > 實(shí)體類
它就是創(chuàng)建我們的service和dao對(duì)象的。
第一個(gè):需要一個(gè)配置文件來配置我們的service和dao配置的內(nèi)容:唯一標(biāo)識(shí)=全限定類名(key=value)
第二個(gè):通過讀取配置文件中配置的內(nèi)容钠怯,反射和創(chuàng)建對(duì)象
配置文件可以是xml也可以是properties
獲取spring的Ioc核心容器佳魔,并根據(jù)id獲取對(duì)象
ApplicationContext的三個(gè)常用實(shí)現(xiàn)類:
ClassPathXmlApplicationContext:它可以加載類路徑下的配置文件,要求配置文件必須在類路徑下晦炊,不在的話加載不了吃引。
FileSystemXmlApplicationContext:它可以加載磁盤任意路徑下的配置文件(必須有訪問權(quán)限)
AnnotationConfigApplicationContext:它是用于讀取注解創(chuàng)建容器的,
核心容器的兩個(gè)接口引發(fā)出的問題
ApplicationContext:
單例對(duì)象適用
它在構(gòu)建核心容器時(shí)刽锤,創(chuàng)建對(duì)象采取的策略是采用立即加載的方式,也就是說朦佩,只要一讀取完配置文件馬上就創(chuàng)建配置文件中的對(duì)象并思。
BeanFactory:
多例對(duì)象適用
它在構(gòu)建核心容器時(shí),創(chuàng)建對(duì)象采取的策略時(shí)采用延遲加載的方式语稠,也就是說宋彼,什么時(shí)候根據(jù)id獲取對(duì)象了,什么時(shí)候才真正的創(chuàng)建對(duì)象仙畦。
//1.獲取核心容器對(duì)象
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
//2.根據(jù)id獲取bean對(duì)象
IAccountService as=(IAccountService)ac.getBean("accountService");
IAccountDao ad=ad.getBean("accountDao.class");
//BeanFactory
Resource resource=new ClassPathResource("bean.xml");
BeanFactory factory=new XmlBeanFactory(resource);
IAccountService as=(IAccountService)ac.getBean("accountService");
把對(duì)象的創(chuàng)建交給spring來管理
spring對(duì)bean的管理細(xì)節(jié)
1.創(chuàng)建bean的三種方式
2.bean對(duì)象的作用范圍
3.bean對(duì)象的生命周期
創(chuàng)建Bean的三種方式
第一種方式:使用默認(rèn)構(gòu)造函數(shù)創(chuàng)建
在spring的配置文件中使用bean標(biāo)簽输涕,配以id和class屬性之后,且沒有其他屬性和標(biāo)簽時(shí)慨畸,采用的就是默認(rèn)構(gòu)造函數(shù)創(chuàng)建bean對(duì)象莱坎,此時(shí)如果類中沒有默認(rèn)構(gòu)造函數(shù),則對(duì)象無法創(chuàng)建
<bean id="accountService" class="com.neusoft.service.imp.AccountServiceImp"></bean>
第二種方式:使用普通工廠中的方法創(chuàng)建對(duì)象
先配置一個(gè)類交給spring檐什,再使用某個(gè)類中的方法創(chuàng)建對(duì)象碴卧,并存入spring容器
<bean id="instanceFactory" class="com.neusoft.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
第三種方式:使用工廠中的靜態(tài)方法創(chuàng)建對(duì)象
使用某個(gè)類中的靜態(tài)方法創(chuàng)建對(duì)象,并存入spring容器
<bean id="accountService" class="com.neusoft.factory.StaticFactory" factory-method="getAccountService"></bean>
bean的作用范圍類調(diào)整
bean標(biāo)簽的scope屬性
作用:用于指定bean的作用范圍
取值:
singleton:單例的(默認(rèn)值)
prototype:多例的
request:作用于web應(yīng)用的請(qǐng)求范圍
session:作用于web應(yīng)用的會(huì)話范圍
global-session:作用于集群環(huán)境的會(huì)話范圍(全局會(huì)話范圍)乃正,當(dāng)不是集群環(huán)境時(shí)住册,就是session
bean對(duì)象的生命周期
單例對(duì)象
出生:當(dāng)容器創(chuàng)建時(shí),對(duì)象出生
活著:只要容器還在瓮具,對(duì)象一直活著
死亡:容器銷毀荧飞,對(duì)象消亡
總結(jié):單例對(duì)象的生命周期和容器相同
<bean id="accountService" class="com.neusoft.service.impl.AccountServiceImpl" scope="singleton" init-method="init" destory-method="destory"></bean>
//獲取核心容器對(duì)象
//在這一步時(shí)就已經(jīng)創(chuàng)建了對(duì)象
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
IAccountService as=(IAccountService) ac.getBean("accountService");
無銷毀的原因:
main方法是一切方法的入口,當(dāng)main方法執(zhí)行完以后名党,里面所有內(nèi)存全部釋放叹阔,包括容器也被釋放了,所以容器還沒來得及調(diào)用銷毀方法就已經(jīng)消失了兑巾,所以需要手動(dòng)提交銷毀方法:ac.close()
這是因?yàn)槲覀冊谇懊嬲{(diào)用的是接口
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
由于多態(tài)条获,我們無法使用在ClassPathXmlApplicationContext中的方法,所以使用本類即可
ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
public class AccountServiceImpl implements IAccountService
{
// @Autowired
@Resource(name = "accountDao")
private IAccountDao accountDao=null;
public AccountServiceImpl(){
System.out.println("對(duì)象創(chuàng)建了");
}
public void init(){
System.out.println("對(duì)象已初始化");
}
public void destory(){
System.out.println("對(duì)象已銷毀");
}
多例對(duì)象
出生:當(dāng)我們使用對(duì)象時(shí)spring框架為我們創(chuàng)建
活著:對(duì)象在使用過程中就一直活著
死亡:當(dāng)對(duì)象長時(shí)間不用蒋歌,且沒有別的對(duì)象引用時(shí)帅掘,由Java的垃圾回收器回收
//1.獲取核心容器對(duì)象
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
//2.根據(jù)id獲取bean對(duì)象
//在這一步時(shí)才創(chuàng)建對(duì)象
IAccountService as=(IAccountService)ac.getBean("accountService");
依賴注入
依賴注入:Dependency Injection
IOC的作用:降低程序間的耦合(依賴關(guān)系)
依賴關(guān)系的管理:以后都交給spring來維護(hù)
在當(dāng)前類需要用到其他類的對(duì)象,由spring為我們提供堂油,我們只需要在配置文件中說明
依賴關(guān)系的維護(hù):就稱之為依賴注入
依賴注入:能注入的數(shù)據(jù)修档,有三類
基本類型和String
其他bean類型(在配置文件中或者注釋配置過的bean)
復(fù)雜類型/集合類型
注入的方式:有三種
第一種:使用構(gòu)造函數(shù)提供
第二種:使用set方法提供
第三種:使用注解提供
構(gòu)造函數(shù)注入:
使用的標(biāo)簽:constructor.arg
標(biāo)簽出現(xiàn)的位置:bean標(biāo)簽的內(nèi)部
標(biāo)簽中的屬性
type:用于指定要注入的數(shù)據(jù)的數(shù)據(jù)類型,該數(shù)據(jù)類型也是構(gòu)造函數(shù)中某個(gè)或某些參數(shù)的類型
Index:用于指定要注入的數(shù)據(jù)給構(gòu)造函數(shù)中指定索引位置的參數(shù)賦值府框,索引的位置是從0開始的
name:用于指定給構(gòu)造函數(shù)中指定名稱的參數(shù)賦值
value:用于提供基本類型和String類型的數(shù)據(jù)
ref:用于指定其他的bean類型數(shù)據(jù)吱窝,它指的就是在spring的Ioc核心容器 中出現(xiàn)過的bean對(duì)象
優(yōu)勢:在獲取bean對(duì)象時(shí),注入數(shù)據(jù)是必須的操作迫靖,否則對(duì)象無法創(chuàng)建成功院峡。
弊端:改變了bean對(duì)象的實(shí)例化方式,使我們在創(chuàng)建對(duì)象時(shí)系宜,如果用不到這些參數(shù)照激,也必須提供。
只能賦給構(gòu)造器中String類型的一個(gè)值name盹牧,并且如果有多個(gè)String類型俩垃,那么賦值哪一個(gè)也不確定,因此type不適合對(duì)于多個(gè)參數(shù)列表的賦值
set方法注入:
涉及的標(biāo)簽:property
出現(xiàn)的位置:bean標(biāo)簽內(nèi)部
標(biāo)簽的屬性:
name:用于指定注入時(shí)所調(diào)用的set方法名稱
value:用于提供基本類型和String類型的數(shù)據(jù)
ref:用于指定其他的bean類型數(shù)據(jù)汰寓,它指的就是在spring的Ioc核心容器中出現(xiàn)過的bean對(duì)象
優(yōu)勢:創(chuàng)建對(duì)象時(shí)沒有明確的限制口柳,可以直接使用默認(rèn)構(gòu)造函數(shù)
弊端:如果有某個(gè)成員必須有值,則讀取對(duì)象可能set方法沒有執(zhí)行
復(fù)雜類型的注入/集合類型的注入
用于給list結(jié)構(gòu)集合注入的標(biāo)簽:list有滑,array跃闹,set
用于給Map結(jié)構(gòu)集合注入的標(biāo)簽:map,props
結(jié)構(gòu)相同,標(biāo)簽可以互換
注解@:
用于創(chuàng)建對(duì)象的
作用就和在xml配置文件中編寫一個(gè)<baen>標(biāo)簽實(shí)現(xiàn)的功能是一樣的
@Component:
作用:用于把當(dāng)前類對(duì)象存入spring容器中
屬性:value:用于指定bean的id辣卒。當(dāng)我們不寫時(shí)掷贾,它的默認(rèn)值時(shí)當(dāng)前類名,且首字母改小寫荣茫。
@Controller:一般用于表現(xiàn)層
@Service:一般用在業(yè)務(wù)層
@Repository:一般用在持久層
以上三個(gè)注解作用和屬性于component一模一樣想帅,是spring框架為我們提供明確的三層使用的注解,使我們的三層對(duì)象更加清晰
用于注入數(shù)據(jù)的
作用就和在xml配置文件中的bean標(biāo)簽中寫一個(gè)<property>標(biāo)簽的作用一樣
Autowired:
作用:自動(dòng)按照類型注入:只要容器中有唯一的一個(gè)bean對(duì)象類型和要注入的變量類型匹配啡莉,就可以注入成功
如果Ioc容器中沒有任何一個(gè)bean的類型和要注入的變量類型匹配港准,則報(bào)錯(cuò)
如果Ioc容器中有多個(gè)類型匹配時(shí),則再進(jìn)行一次變量名匹配咧欣,當(dāng)變量名與某個(gè)bean的id相同時(shí)才能運(yùn)行
出現(xiàn)位置:可以是變量上浅缸,也可以是方法上
細(xì)節(jié):在使用注解注入時(shí),set方法就不是必須的
Qualifier:
作用:在按照類中注入的基礎(chǔ)之上再按照名稱注入魄咕。它再給類成員注入時(shí)不能單獨(dú)使用衩椒。但是在給方法參數(shù)注入時(shí)可以。
屬性:value哮兰,用來指定注入bean的id毛萌。
Resource:
作用:直接按照bean的id注入。它可以獨(dú)立使用
屬性:name喝滞,用于指定bean的id阁将。
以上三種注入都只能注入其他bean類型的數(shù)據(jù),而基本類型和String類型無法使用上述注解實(shí)現(xiàn)右遭。
Value:
作用:用于注入基本類型和String類型的數(shù)據(jù)
屬性:value做盅,用于指定數(shù)據(jù)的值,它可以使用spring中SpEL(也就是spring的el表達(dá)式)
用于改變作用范圍的
作用就和在bean標(biāo)簽中使用scope屬性實(shí)現(xiàn)的功能一致
Scope:
作用:用于指定bean的作用范圍
屬性:value窘哈,指定范圍的取值吹榴,常用取值:singleton,prototy
和生命周期相關(guān)
作用和在bean標(biāo)簽中使用init-method和destroy-method的作用一致
PreDestroy:
作用:用于指定銷毀方法
PostConstruct:
作用:用于指定初始化方法