IOC底層原理
??控制反轉,把物件創建和物件之間的呼叫程序,交給Spring進行管理,使用IOC目的:降低耦合度
底層原理:
xml決議、工廠模式、反射
我們先來看看關聯兩個類最直接的實作方式是怎樣的:
public class UserService {
public void execute(){
UserDao userDao = new UserDao();
userDao.add();
}
}
class UserDao{
public void add(){
//這里是方法體部分
}
}
說明:通過在UserService 類當中new一個關于UserDao的物件,并且呼叫其方法,很明顯這種方式是可以實作關聯的,但是這兩個類之間的耦合度太高,當UserDao內部代碼修改之后,UserService相應的呼叫也需要修改,
接下來使用工廠模式進行解耦操作:
public class UserService {
public void execute(){
//UserDao userDao = new UserDao();
//userDao.add();
UserDao userDao = UserFactory.getDao();
userDao.add();
}
}
class UserDao{
public void add(){
//這里是方法體部分
}
}
class UserFactory{
public static UserDao getDao(){
return new UserDao();
}
}
說明:對于工廠設計模式來說,物件的new操作不需要自己直接來進行,只需要跟第三方的Fantory進行交涉就行了,工廠設計模式確實是降低耦合度的一種方式,但并不是最好的一種方式,那么下面就需要介紹IOC解耦程序了,
IOC解耦程序:
第一步:xml組態檔,配置創建的物件
<bean id="user" class="com.spring.User"></bean>
//這個class欄位內容是你的專案種User類的路徑(包名.類名)
第二步:有UserService類和UserDao類,同樣創建一個工廠類
class UserFactory{
public static UserDao getDao(){
//1.xml決議
//String classValue = class屬性值;
//2.通過反射創建物件(得到相應類的位元組碼檔案)
//Class clazz = Class.forName(classValue);
//return (UserDao)clazz.newInstance();
}
}
說明:IOC可以進一步降低代碼間的耦合度,將物件的創建以及物件之間的呼叫都交給Spring來管理,
IOC介面
- IOC思想基于IOC容器來完成,IOC容器底層就是物件工廠
- Spring提供IOC容器的兩種實作方式(兩個介面):
BeanFactory:IOC容器基本實作,是Spring內部的使用介面,不提供開發人員使用,加載組態檔的時候不會創建物件,在獲取(使用)物件時才去創建物件,
ApplicationContext:介面的子介面,提供更多更強大的功能,一般由開發人員進行使用,加載組態檔的時候就會進行物件的創建, - ApplicationContext介面的主要實作類

IOC操作Bean管理(基于XML)
什么是Bean管理?
Bean管理指的是兩個操作,1.Spring創建物件;2.Spring注入屬性
基于xml方式實作程序:
??1.在Spring組態檔中,使用bean標簽,標簽里面添加對應屬性,就可以實作物件創建,
<bean id="user" class="com.spring.User"></bean>
bean標簽里面有很多屬性:
id:類的唯一標識
class:類全路徑(包+類路徑)
name:和id屬性類似,可以加特殊符號(幾乎不使用這個屬性)
注意:bean標簽在創建物件的時候,默認也是執行無參構造方法,
??2.基于xml方式注入屬性
- 使用set()方法來實作屬性注入:
public class UserService {
private String name;
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
UserService userService = new UserService();
userService.setName("張三");
}
}
上面的程序可以使用xml組態檔的形式來實作:
<!--物件創建-->
<bean id="user" class="com.spring.User">
<!-- 設定欄位屬性值-->
<property name="userName" value="張三"></property>
</bean>
- 使用有參構造方法注入:
public class UserService {
private String name;
public UserService(String name) {
this.name = name;
}
public static void main(String[] args) {
UserService userService = new UserService("張三");
}
}
上面的程序可以使用xml組態檔的形式來實作:
<bean id="user" class="com.spring.User">
<constructor-arg name="userName" value="張三"></constructor-arg>
</bean>
XML注入其它型別屬性
- 設定空值null
<!--物件創建-->
<bean id="user" class="com.spring.User">
<!-- 設定欄位屬性值-->
<property name="userName">
<null></null>
</property>
</bean>
- 設定的屬性值包含特殊符號
<!-- 設定欄位屬性值-->
<property name="userName">
<value><![CDATA[<<張三>>]]></value>
</property>
- 注入屬性-外部bean
1.創建兩個類service類和dao類
2.在service里面呼叫dao里面的方法
import dao.UserDao;
public class UserService {
//1.創建UserDao型別屬性,生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("添加方法");
userDao.updata();
//原始方式:new物件+呼叫方法
/*UserDao userDao = new UserDaoImpl();
userDao.updata();*/
}
}
public class UserDaoImpl implements UserDao{
@Override
public void updata() {
System.out.println("dao updata");
}
}
<!-- 1.service和dao物件創建-->
<bean id="userService" class="service.UserService">
<!--注入UserDao物件
name屬性:類里面的屬性名稱
ref屬性:創建UserDao物件bean標簽id值
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="dao.UserDaoImpl"></bean>
- 注入屬性-內部bean和級聯賦值
舉例一對多的關系:學校和學生
public class School {
private String sch_name;
public void setSch_name(String sch_name) {
this.sch_name = sch_name;
}
//重寫toString()方法
public String toString(){
return sch_name;
}
}
public class Student {
//設定學生屬性
private String stu_name;
private String stu_gender;
private School stu_school;
//生成每個屬性對應的set方法
public void setStu_name(String stu_name) {
this.stu_name = stu_name;
}
public void setStu_gender(String stu_gender) {
this.stu_gender = stu_gender;
}
public void setStu_school(School stu_school) {
this.stu_school = stu_school;
}
//設定一個方法
public void print(){
System.out.println(stu_name+" "+stu_gender+" "+stu_school.toString());
}
}
<!--1.創建物件-->
<bean id="student" class="bean.Student">
<!-- 2.給該物件設定其屬性-->
<property name="stu_name" value="張三"></property>
<property name="stu_gender" value="男"></property>
<property name="stu_school">
<bean id="school" class="bean.School">
<property name="sch_name" value="某大學"></property>
</bean>
</property>
</bean>
上面的xml組態檔也可以使用級聯賦值方式:
(1)第一種方式:也即是外部bean方法
<!--1.創建物件-->
<bean id="student" class="bean.Student">
<!-- 2.給該物件設定其屬性-->
<property name="stu_name" value="張三"></property>
<property name="stu_gender" value="男"></property>
<property name="stu_school" ref="school"></property>
</bean>
<bean id="school" class="bean.School">
<property name="sch_name" value="某大學"></property>
</bean>
(2)第二種方式:
<!--1.創建物件-->
<bean id="student" class="bean.Student">
<!-- 2.給該物件設定其屬性-->
<property name="stu_name" value="張三"></property>
<property name="stu_gender" value="男"></property>
<property name="stu_school" ref="school"></property>
<property name="stu_school.sch_name" value="某小學"></property>
</bean>
<bean id="school" class="bean.School">
<!--<property name="sch_name" value="某大學"></property>-->
</bean>
Tips:這個似乎是有優先級內味兒了,某大學那一欄的屬性值可以去掉,只需要創建school物件即可,注意哈,需要生成Student類當中屬性stu_school的get方法,
- 注入集合屬性
(1)屬性為陣列
(2)屬性為List集合
(3)屬性為Map集合
(4)屬性為Set集合
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Student {
private String[] names;
private List<String> list;
private Map<String,String> map;
private Set<String> set;
public void setNames(String[] names) {
this.names = names;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void print(){
System.out.println(Arrays.toString(names));
System.out.println(list);
System.out.println(map);
System.out.println(set);
}
}
<!--1.創建物件-->
<bean id="student" class="collectiontype.Student">
<!--2.設定屬性-->
<property name="names">
<array>
<value>張三</value>
<value>李四</value>
</array>
</property>
<property name="list">
<list>
<value>張三</value>
<value>李四</value>
</list>
</property>
<property name="map">
<map>
<entry key="張三" value="張三"></entry>
<entry key="李四" value="李四"></entry>
</map>
</property>
<property name="set">
<set>
<value>張三</value>
<value>李四</value>
</set>
</property>
</bean>
</beans>
對集合提取公共代碼部分
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 1.提取list集合型別屬性注入-->
<util:list id="studentList">
<value>張三</value>
<value>李四</value>
</util:list>
<!-- 2.提取list集合型別屬性注入使用-->
<bean id="student" class="collectiontype.Student">
<property name="list" ref="studentList"></property>
</bean>
</beans>
??Spring有兩種型別的bean,一種普通bean,另外一種是工廠bean (FactoryBean),
(1)普通bean:在組態檔中定義的bean型別就是回傳型別
(2)工廠bean:在組態檔中定義的bean型別可以和回傳型別不一樣
public class MyBean implements FactoryBean<Course> {
@Override
public Course getObject() throws Exception {
ApplicationContext context =
new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("course",Course.class);
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
}
<!-- 1.創建物件-->
<bean id="mybean" class="bean.MyBean"></bean>
<bean id="course" class="collectiontype.Course">
<property name="course_name" value="語文"></property>
</bean>
有關bean作用域問題:
1.在Spring框架當中,需要明確設定創建的bean實體是單實體還是多實體,默認情況下,bean是單實體物件,
2.如何設定單實體還是多實體?
??在Spring組態檔bean標簽里面有屬性(scope)用于設定單實體還是多實體,
scope屬性值:
??默認值singleton:表示是單實體物件
??prototype:表示是多實體物件
兩者的區別是啥呢:
??scope的屬性值是singleton的時候,加載Spring組態檔的時候就會創建單實體物件;當scope的屬性值是prototype的時候,不是在加載Spring組態檔的時候創建物件,在呼叫getBean方法的時候創建多實體物件,
有關bean生命周期問題:
生命周期:一個物件從創建到銷毀的程序
bean的生命周期階段:
(1)通過構造器創建bean實體(無參構造方法)
(2)為bean的屬性設定值和對其他bean參考(呼叫set方法)
→→把bean實體傳遞到bean后置處理器的方法
(3)呼叫bean的初始化方法(需要進行配置初始化的方法)
→→把bean實體傳遞到bean后置處理器的方法
(4)bean可以使用了(對 象獲取到了)
(5)當容器關閉的時候,呼叫bean的銷毀的方法(需要進行配置銷毀的方法)
xml自動裝配問題
??上面討論的有關使用value設定屬性值等等的xml檔案配置問題都是基于手動配置的,接下來我要講的就是xml自動裝配問題,
根據指定裝配規則(屬性名稱或者屬性型別),Spring自動將匹配的屬性值進行注入,
bean標簽屬性autowire用來自動裝配,autowire屬性常用的兩個值:
(1)byName:根據屬性名稱注入,要求是注入值bean的id值和類屬性名稱一樣,
(2)byType:根據屬性型別注入,
<bean id="student" class="autowire.Student" autowire="byName">
<!-- <property name="school_name" ref="school"></property>-->
</bean>
<bean id="school_name" class="autowire.School"></bean>
<bean id="student" class="autowire.Student" autowire="byType">
<!-- <property name="school_name" ref="school"></property>-->
</bean>
<bean id="school_name" class="autowire.School"></bean>
引入外部屬性檔案
(1)直接配置資料庫資訊(配置德魯伊連接池)
<?xml version="1.0" encoding="UTF-8"?>
<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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--直接配置連接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
(2)通過引入外部屬性檔案配置資料庫連接池
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--引入外部屬性檔案-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置連接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
</beans>
Tips:需要使用名稱空間context
下期博客接著講解IOC操作Bean管理(基于注解)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/247648.html
標籤:java
下一篇:上班摸魚 手敲求水仙花數的代碼!
