java-spring
Spring-IOC
ioc概念
控制反轉
把物件建立和物件之間的呼叫過程,交給Spring 進行管理。
目的就是,為了降低耦合度,因為當你想在一個類當中呼叫另外一個類的方法,你需要獲得另外一個類的例項
IOC的底層原理:
包括xml解析,工廠模式,反射
引入工廠模式之後:
IOC解耦過程
IOC介面:
1Ioc思想基於IOC容器完成,IO容器底層就是物件工廠 2Spring提供IOC容器實習兩種方式:兩個介面 1)BeanFactory :IOC容器基本實現,Spring內部的使用介面,不提供給開發人員進行使用 2)ApplicationContext :BeanFactory介面的子介面,提供更強大的功能,一般開發人員使用 區別: BeanFactory 載入配置檔案的時候不會建立物件,在獲取物件的時候才建立。 ApplicationContext ,載入檔案的時候,會將配置檔案裡面的物件進行建立。
獲取IOC容器的方式
通過beanFactory
通過applicationContext獲取
3 ApplicationContext介面實現類
FileSystemXmlApplicationContext從碟符路徑開始查詢配置檔案,絕對路徑
ClassPathXmlApplicationContext專案路徑下查詢-----一般使用
IOC操作Bean管理
Bean管理是什麼:
1Spring建立物件
2Spring注入屬性
Bean管理操作兩種方式
基於xml配置檔案方式實現
基於註解方式實現
JOC操作Bean管理--基於xml方式
基於xml方式建立物件
</bean> <bean id="usert" class="com.quan.Usert" > </bean>
1)在sprin配置檔案中,使用bean標籤,標籤理新增相應的屬性,就可以實現物件建立
2)bean標籤的屬性
id:屬性 =唯一標識
class屬性=類的全路徑
3)預設使用無參構造方法完成物件的建立
bean的作用域
單例 - 每個Spring IoC 容器返回一個bean例項 singleton 原型- 當每次請求時返回一個新的bean例項 prototype 請求 - 返回每個HTTP請求的一個Bean例項 會話 - 返回每個HTTP會話的一個bean例項 全域性會話- 返回全域性HTTP會話的一個bean例項 預設是單例
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
for (int i = 0; i < 3; i++) {
User user = (User)ac.getBean("user");
System.out.println(user);
}
singleton作用域
共享一個例項bean,只建立一個例項,
結果為:
/*socpe為sigleon的時候 com.quan.User@67784306 com.quan.User@67784306 com.quan.User@67784306 */
prototype作用域
每次注入這個類的時候,都建立一個例項
v/*socpe為prototype的時候 com.quan.User@63753b6d com.quan.User@6b09bb57 com.quan.User@6536e911 */
bean標籤的屬性init-method= destroy-method=
先說兩個介面先:
InitializingBean DisposableBean 標記介面 ,
主要實現Spring 執行bean時的初始化和銷燬時某些方法
實現InitializingBean ,需要實現afterPropertiesSet,就是設定所有的屬性之後做什麼
實現DisposableBean 實現destory(),就是Spring 容器釋放該bean之後做些什麼
public class InitialDisp implements InitializingBean, DisposableBean {
public void destroy() throws Exception {
System.out.println("destroy");
}
public void afterPropertiesSet() throws Exception {
System.out.println("afterProper");
}
}
執行:
public class BETest {
public static void main(String[] args) {
/*
ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable
ApplicationContext:應用上下文
Lifecycle:負責context的生命週期進行管理,提供start(),stop() 以及isRunning()
Closeable:用於關閉元件,釋放資源
ConfigurableApplicationContext 介面的作用就是設定上下文 ID,設定父應用上下文,新增監聽器,重新整理容器,關閉,判斷是否活躍等方法
*/
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
InitialDisp id = (InitialDisp)ac.getBean("initdesp");
System.out.println(id);
ac.close();
}
}
/*
re:
afterProper
com.quan.hll.InitialDisp@1f36e637
destroy
*/
但是不建議使用這兩個介面
可以指定類中的某個方法為兩個階段的方法:init-method= destroy-method=
上面的類不在繼承那兩個介面
再bean配置檔案當中:
<bean id="initdesp" class="com.quan.hll.InitialDisp" init-method="afterPropertiesSet" destroy-method="destroy"></bean>建議使用init-method和destroy-methodbean在Bena配置檔案,而不是執行 InitializingBean 和 DisposableBean 介面,也會造成不必要的耦合程式碼在Spring。
設定bean載入和銷燬所呼叫的方法
</bean> <bean id="usert" class="com.quan.Usert" init-method="init" destroy-method="destroy"> </bean>
test;
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
Usert usert = (Usert)ac.getBean("usert");
usert.say();
//關閉ioc容器
((ClassPathXmlApplicationContext) ac).close();
基於xml方式注入屬性
1)DI: 依賴注入,就是注入屬性,是IOC的一種實現方式
依賴注入-setter方法;
11類需要各個屬性的set方法
22配置檔案中先建立物件,再注入屬性
依賴注入---構造方法
1)需要建立有參建構函式
2)配置檔案中使用constructor-arg標籤
第一個類:
View Code第二個類:
View Codespring-config.xml配置
<!-- 建立User物件,id是這個資源的唯一表示-->
<bean id="user" scope="prototype" class="com.quan.User">
<!-- 通過構造方法注入-->
<constructor-arg index="0" value="QQgou"/>
<constructor-arg index="1" ref="usert"/>
<!-- 這裡的user例項裡面的name屬性會被下面的設定替代,如果沒有就是構造器的值-->
<property name="name">
<value>QQSpring</value>
</property>
<!-- name這裡是指User類裡面的屬性usert 這裡的ref是指下面的bean-->
<property name="usert" ref="usert">
</property>
</bean>
<bean id="usert" class="com.quan.Usert" init-method="init" destroy-method="destroy">
</bean>
re;
init see you
how to sayQQSpring
see you
注:加顏色就是通過構造方法注入的形式,裡面還有屬性是其他類的設定
IOC操作Bean管理-xml注入其他型別屬性
字面量
null值
再熟悉值裡面不要設定value屬性,直接加入null標籤
<bean id="user" class="com.quan.hlll.User"> <property name="name"> <null></null> </property> </bean>
特殊符號<<>>
進行轉義操作
<bean id="user" class="com.quan.hlll.User"> <property name="name" value="<><<南京>>"></property> </bean>
把帶特殊符號內容寫到CDATA
<property name="name"> <value><![CDATA[<<南京>>]]></value> </property>
注入屬性-外部bean
person累有一個屬性為hello物件型別
<bean id="person" class="com.quan.hll.javaConfig.Person.Person"> <constructor-arg index="0" value="QQQ"/> <constructor-arg index="1" ref="hello" /> </bean> <bean id="hello" class="com.quan.hll.javaConfig.Hello.Hello"></bean>
注意屬性-內部bean和級聯賦值
View Code通過建構函式(其實set方法也是可以的)
<bean id="person" class="com.quan.hll.javaConfig.Person.Person"> <constructor-arg index="0" value="QQQ"/> <constructor-arg index="1" > <bean class="com.quan.hll.javaConfig.Hello.Hello"></bean> </constructor-arg> </bean>
內部定義的累有屬性的時候
注意:建議在類的內部進行內部類的定義:
<bean id="person" class="com.quan.hll.javaConfig.Person.Person"> <constructor-arg index="0" value="QQQ"/> <constructor-arg index="1" > <bean class="com.quan.hll.javaConfig.Hello.Hello"> <property name="msg"> <value>ourmsg</value> </property> </bean> </constructor-arg> </bean>
bean屬性值的注入兩種xml格式
類
View Code<!-- 使用屬性標籤property其的下級value屬性進行值的注入,--> <bean id="mconstructor" class="com.quan.hll.manyConstruntor.MConstructor" > <property name="name" > <value>quan</value> </property> <property name="addr"> <value>gd</value> </property> <property name="age"> <value>23</value> </property> </bean>
<!-- 使用快捷方式進行值的注入,--> <bean id="mconstructor" class="com.quan.hll.manyConstruntor.MConstructor" > <property name="age" value="23"/> <property name="addr" value="gd"/> <property name="name" value="q1234"/> </bean>
IOC操作Bean管理(xml-注入集合屬性)
格式:
<list value-type="java.lang.String"> <value>list裡面的元素</value> ... </list> <set> <value>set元素</value> ... </set> <map> <entry key=key值 value=key值對應的value/> .... </map> <props> <prop key=key值>value值寫這裡</prop> ..... </props>
eg
<bean id="springlist" class="com.quan.hll.List.SpringList"> <!-- list--> <property name="lists" > <list value-type="java.lang.String"> <value>quan</value> <value>quan</value> <value>quan2</value> </list> </property> <!-- set--> <property name="sets"> <set> <!-- 因為set屬性不允許重複,只保留一個--> <value>quan</value> <value>quan</value> <value>quan2</value> </set> </property> <!-- Map--> <property name="maps"> <map> <!-- 同樣只保留後者--> <entry key="one" value="QQQ"/> <entry key="one" value="ZZZ"/> <entry key="two" value="ZZZ"/> </map> </property> <!-- properties--> <property name="properties"> <props> <prop key="quan">shige213</prop> <prop key="zhi">shige321</prop> </props> </property> </bean>View Code
類:
package com.quan.hll.List; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class SpringList { private List<Object> lists; private Set<Object> sets; private Map<Object,Object> maps; private Properties properties; public List<Object> getLists() { return lists; } public void setLists(List<Object> lists) { this.lists = lists; } public Set<Object> getSets() { return sets; } public void setSets(Set<Object> sets) { this.sets = sets; } public Map<Object, Object> getMaps() { return maps; } public void setMaps(Map<Object, Object> maps) { this.maps = maps; } public Properties getProperties() { return properties; } public void setProperties(Properties properties) { this.properties = properties; } }
列印類:
[quan, quan, quan2] {one=ZZZ, two=ZZZ} {quan=shige213, zhi=shige321} [quan, quan2]
spring注入日期:
<bean id="sdate" class="com.quan.hll.List.Sdate"> <!-- 使用下面會報錯,必須使用格式話進行格式話--> <!-- <property name="date" value="2020-12-20"/>--> <!-- Cannot convert value of type [java.lang.String] to required type --> <!-- [java.util.Date] for property 'date': no matching edit--> <property name="date"> <bean factory-bean="dataFormat" factory-method="parse"> <constructor-arg value="2020-12-20"></constructor-arg> </bean> </property> </bean> <bean id="dataFormat" class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-MM-dd"/> </bean>
re:Sdate{date=Sun Dec 20 00:00:00 CST 2020}
PropertyPlaceholderConfigurer對映
用於配置檔案的管理,
datasource.properties
driver=com.jdbc.mysql.connection url=jdbc:mysql:localhost:3306 username=root password=2009
<!-- 載入PropertyPlaceholderConfigurerbean,並指定檔案位置--> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>datasource.properties</value> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driver}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> <property name="url" value="${url}"/> </bean>
spring-bean的繼承
這裡不是在java下建立類去extend而是通過bean的配置檔案去實現
主要是bean父設定一個模板或者屬性,子bean公用這個屬性或者模板
類:
public class BasePlace {
private String place;
private String name;
下面父bean只是共享自己的name的屬性值
<bean id="base" class="com.quan.hll.expand.BasePlace" > <property name="name" value="Q"/> </bean> <bean id="expandbase" parent="base"> <property name="place" value="sz"/> </bean>
注意:其實expandbase這個bean也是com.quan.hll.expand.BasePlace類
加入下面的這個bean標籤的屬性是說明父bean不可被例項化:
<bean id="base" class="com.quan.hll.expand.BasePlace" abstract="true"> 如果呼叫: BasePlace bb = (BasePlace)ac.getBean("base"); 報錯
加入下面一句,子類bean新設定的屬性值會覆蓋父bean
<property name="name" value="QQ"/>
BasePlace{place='sz', name='Q'}
@Required註解依賴檢查,指定類中的屬性檢查,部分!!!
單單加入這個還是不生效,需要在bean.xml檔案裡面引入解析註解的bean
適用於bean屬性setter方法,並表示受影響的bean屬性必須在XML配置檔案在配置時進行填充。否則,容器會丟擲一個BeanInitializationException異常。
public class BasePlace {
private String place;
private String name;
@Required
public void setName(String name) {
this.name = name;
}
bean。xml
<bean id="base" class="com.quan.hll.expand.BasePlace" > <property name="place" value="ShenZhen"/> </bean>
baocuo
org.springframework.beans.factory.BeanInitializationException:
Property 'name' is required for bean 'base'
註冊一個RequiredAnnotationBeanPostProcessor以瞭解在bean配置檔案@Required註解
111
設定context:
<context:annotation-config/>
22設定bean
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
自定義@required註解名字(換名字)
編寫註解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyRequired { }
註冊註解:
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"> <property name="requiredAnnotationType" value="com.quan.hll.MyRequired"></property> </bean>
使用即可:
public class BasePlace { private String place; private String name; @MyRequired public void setName(String name) { this.name = name; }
使用javaConfig(註解)代替spring-config.xml來配置bean
/*
通過java類來載入bean,註解
*/
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HelloConfig {
@Bean(name = "hello")
public Hello hello(){
return new Hello();
}
}
相當於:
<bean id="hello" class="com.quan.hll.javaConfig.Hello" ></bean>
//通過JavaConfig的類物件來獲取ApplicationConext // ApplicationContext ac = new AnnotationConfigApplicationContext(HelloConfig.class); //通過spring-config.xml配置檔案來進行bean載入 ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
多個bean模組化設定配置檔案
多個建構函式的歧義
package com.quan.hll.manyConstruntor;
public class MConstructor{
private String name;
private int age;
private String addr;
/*
兩個建構函式,可能會出現起義
*/
public MConstructor(int age, String name, String addr) {
this.name = name;
this.age = age;
this.addr = addr;
}
public MConstructor(String name, int age, String addr) {
this.name = name;
this.age = age;
this.addr = addr;
}
@Override
public String toString() {
return "MConstructor{" +
"name='" + name + '\'' +
", age=" + age +
", addr='" + addr + '\'' +
'}';
}
}
/*
第一次沒有指定型別出現這個結果:
MConstructor{name='23', age=199, addr='123'}
*/
<!-- 兩個建構函式,可能會出現起義--> <!-- <bean id="mconstructor" class="com.quan.hll.manyConstruntor.MConstructor" >--> <!-- <constructor-arg >--> <!-- <value>199</value>--> <!-- </constructor-arg>--> <!-- <constructor-arg>--> <!-- <value>23</value>--> <!-- </constructor-arg>--> <!-- <constructor-arg>--> <!-- <value>123</value>--> <!-- </constructor-arg>--> <!-- </bean>--> <!-- 為建構函式指定的確切資料型別,--> <bean id="mconstructor" class="com.quan.hll.manyConstruntor.MConstructor" > <constructor-arg type="java.lang.String" > <value>199</value> </constructor-arg> <constructor-arg type="int"> <value>23</value> </constructor-arg> <constructor-arg type="java.lang.String"> <value>123</value> </constructor-arg> </bean>
多個配置檔案歸結到一個配置檔案
<import resource="hello-config.xml"/> <import resource="person-config.xml"/>
SpEL(Spring Expression Language),