【Spring】- 兩種IOC容器區別
IOC容器自動管理需要使用的Bean,提高程式碼的重用性,同時也達到解耦的目的,IOC實現Bean管理的方式主要是依靠動態代理和反射機制原理,使用動態代理可直接代理目標Bean,實現Bean的高效管理,動態代理可代理目標介面實現Spring框架的攔截器、通知等AOP功能,實現Bean在IOC容器裡面的全域性管理,反射機制主要用於Bean的自動生成,當程式需要使用IOC容器中的Bean時,IOC會根據applicationContext.xml Bean的配置情況通過反射機制自動生成Bean,供外部呼叫,同時IOC容器提供對Bean的作用域、生命週期等管理。
2種IOC容器:BeanFactory/ApplicationContext
-
BeanFactory:主要提供一些IOC的基本功能,像對配置檔案的屬性值填充的高階功能,BeanFactory是無法處理的
-
ApplicationContext: 雖然也是實現BeanFactory介面,但是其的工作方式和BeanFactory略有不同,例如ApplicationContext在處理配置檔案時可以一次性處理多個,從而實現整個專案的功能模組化開發,常見的Web專案中Spring、Springmvc、shiro等框架都配置獨立的配置檔案,通過ApplicationContext可處理多個配置檔案特性,在Spring框架的總控配置檔案中引入達到模組聚合的效果,類似Maven中的Modules功能(BeanFactory的高階版本)
applicationContext.xml:
<?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" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- bean分散配置,通過設定property-placeholder設定屬性檔案, 並在實際bean初始化時使用$佔位符引出處理,context在spring容器視為bean(特殊) <context:property-placeholder location="com/zhiwei/dispatch/database.properties,com/zhiwei/ioc/databaseBack.properties"/> --> <!-- 引入多個屬性檔案的另一種形式 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:com/zhiwei/ioc/database.properties</value> <value>classpath:com/zhiwei/ioc/databaseBack.properties</value> </list> </property> </bean> <bean id="database" class="com.zhiwei.ioc.Database" > <property name="databaseName" value="${databaseName}"/> <property name="driverName" value="${driverName}"/> <property name="url" value="${url}"/> <property name="userName" value="${userName}"/> <property name="passwd" value="${passwd}"/> </bean> <bean id="databaseBack" class="com.zhiwei.ioc.Database" name="aliaseName" scope="prototype" > <property name="databaseName" value="${databaseNameBack}"/> <property name="driverName" value="${driverNameBack}"/> <property name="url" value="${urlBack}"/> <property name="userName" value="${userNameBack}"/> <property name="passwd" value="${passwdBack}"/> </bean> </beans>
資料庫屬性封裝類:Database.java
package com.zhiwei.ioc;
//資料庫引數配置類
public class Database {
private String databaseName;
private String driverName;
private String url;
private String userName;
private String passwd;
public String getDatabaseName() {
return databaseName;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
public String getDriverName() {
return driverName;
}
public void setDriverName(String driverName) {
this.driverName = driverName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
@Override
public String toString() {
return "Database [dabaseName=" + databaseName + ", driverName=" + driverName + ", url=" + url + ", userName="
+ userName + ", passwd=" + passwd + "]";
}
}
資料庫測試屬性配置檔案:database.properties、databaseBack.properties
databaseName=MySql
driverName=jdbc\uFF1Amysql\:mysqlDriver
url=com.mysql.jdbc\://127.0.0.1.1\:1433/test
userName=root
passwd=xiaoyang
databaseNameBack=MySqlBack
driverNameBack=jdbc\uFF1Amysql\:mysqlDriverBack
urlBack=com.mysql.jdbc\://127.0.0.1.1\:1433/testBack
userNameBack=rootBack
passwdBack=xiaoyangBack
BeanFactory容器測試類:
package com.zhiwei.ioc;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
/***
* BeabFactory容器的缺陷:
* ①:不會解析${userName}類似的表示式,只會直接獲取property標籤裡面value的文字值
* @author Yang Zhiwei
*
*/
public class BeanFactoryIOC {
@SuppressWarnings("unused")
public static void main(String[] args) {
//StringUtils.cleanPath:格式化linux形式的檔案路徑:\\-->/ 開頭不需要/
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("com/zhiwei/ioc/applicationContext.xml"));
String[] aliases=beanFactory.getAliases("databaseBack"); //獲取bean的別名
System.out.println("beanName別名:"+aliases[0]);
String[] beforeBeanNames=beanFactory.getSingletonNames();
System.out.println("beforeBeanNames:"+beforeBeanNames.length);
//注意只有在IOC容器裡面的Bean被使用的時候才會進行註冊:標記該類已經例項化可以使用
Database db=(Database) beanFactory.getBean("database");
Database dbback=(Database) beanFactory.getBean("databaseBack");
System.out.println(db);
//因為databaseBack設定為prototype的作用域,因此只能獲取單例的database的資料
String[] afterBeanNames=beanFactory.getSingletonNames();
System.out.println("afterBeanNames:"+afterBeanNames.length);
System.out.println(beanFactory.containsLocalBean("database")); //bean工廠是否包含bean
}
}
結果:
BeanFactory是無法對${}引用資原始檔變數進行解析處理
ApplicationContext測試類:
package com.zhiwei.ioc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/***
* Spring IOC容器的兩種實現方式:
* 簡單:BeanFactory 複雜:ApplicationContext
* @author Yang Zhiwei
*
*/
public class MainTest {
public static void main(String[] args) {
/*
*將屬性檔案注入IOC容器,並通過Javabean的形式獲取
*一般用來放置配置檔案,進行初始化操作
*/
ApplicationContext ac=new ClassPathXmlApplicationContext("com/zhiwei/ioc/applicationContext.xml");
Database db=(Database) ac.getBean("database");
Database dbBack=(Database) ac.getBean("databaseBack");
System.out.println(db);
System.out.println("資料庫:"+db.getDatabaseName());
System.out.println("資料庫Back:"+dbBack.getDatabaseName());
}
}
結果:
ApplicationContext 可對 ${} 引用資原始檔變數的形式解析處理,在大型的專案開發中,不同的框架都具有各自的配置檔案,如果全部硬塞在一個總的配置檔案中對於後續的專案維護絕對是一場噩夢,RDBMS配置檔案、資料庫配置檔案、快取伺服器配置檔案、快取框架配置檔案、安全框架配置檔案、MVC框架配置檔案等等,因為BeanFactory的效能弱的原因,現在的Spring專案中ApplicationCont