Spring IoC (二)
》Bean 的作用域
Spring 提供了五种作用域
1、singleton(单例模式) 在Spring 中仅存在一个共享的实例
2、prototype(原型模式) 每次从容器中获取一个新的实例
3、request 每次HTTP 请求都会创建一个新的Bean 实例
4、session 同一个HTTP 请求共享一个Bean 实例
5、global session 同一个全局Session 共享一个Bean 实例
这里我们主要讲 前两者
<!--
1、单例模式
<bean id="scopeTest" class="com.kgc.scope.ScopeTest" scope="singleton" ></bean>
2、原型模式
<bean id="scopeTest" class="com.kgc.scope.ScopeTest" scope="prototype" ></bean>
注:Bean 的作用域默认是单例模式
-->
<bean id="scopeTest" class="com.kgc.scope.ScopeTest"></bean>
测试代码:
ApplicationContext atc = new ClassPathXmlApplicationContext("applicationContext-scope.xml");
ScopeTest s1 = (ScopeTest)atc.getBean("scopeTest");
ScopeTest s2 = (ScopeTest)atc.getBean("scopeTest");
ScopeTest s3 = (ScopeTest)atc.getBean("scopeTest");
// 在Object 里继承toString 方法 -> 类型@内存地址
// 1.1、如果内存地址一致,则说明是单例
// 1.2、如果内存地址不一致,则说明每次都创建新的实例
System.out.println("s1="+s1.toString());
System.out.println("s2="+s2.toString());
System.out.println("s3="+s3.toString());
》Spring 多配置文件
> 最简单的 数组形式 String[] 因为 通过ClassPathXmlApplicationContext 实例化,传入多个配置文件,默认是可以读多个配置文件的
// 通过读取多个配置文件的形式 ,进行配置
public static void test01(){
// 1、有一个是String[] 的一个方法
// 通过ClassPathXmlApplicationContext 实例化,传入多个配置文件
String[] confs = new String[2];
confs[0] = "applicationContext.xml";
confs[1] = "applicationContext-scope.xml";
ApplicationContext atc = new ClassPathXmlApplicationContext(confs);
Api api = (Api)atc.getBean("api");
api.run();
ScopeTest st = (ScopeTest)atc.getBean("scopeTest");
st.run();
}
》 通过import 标签,引入多个配置文件(常用)
// 实际工作中,会添加一个总的配置文件,主要使用import标签,几乎不做任何与业务有关的内容
// 通过import 标签,引入多个配置文件
// 在 xml 文件中 添加 <import resource="applicationContext-scope.xml"/>
// <import resource="applicationContext.xml"/>
public static void test02(){
ApplicationContext atc = new ClassPathXmlApplicationContext("applicationContext-core.xml");
Api api = (Api)atc.getBean("api");
api.run();
ScopeTest st = (ScopeTest)atc.getBean("scopeTest");
st.run();
}
xml 配置文件
<import resource="applicationContext-scope.xml"/>
<import resource="applicationContext.xml"/>
》 依赖注入方式
<bean id="constractDemo" class="com.kgc.ios.inject.ConstractDemo"></bean>
依赖注入主要有三种方式:
> Setter 方法注入
<!-- Setter 方法注入 -->
<property name="message" value="Hello KGC Spring!"></property>
// 1、Setter 方法注入
public void setMessage(String message) {
this.message = message;
}
> 构造方法注入
<!-- 构造器注入
1、按顺序匹配 -->
<constructor-arg type="String" value="Hello Kgc Spring!"></constructor-arg>
<!-- 2、按类型匹配 如果有相同类型 -->
<constructor-arg type="String" value="Hello Kgc Spring!"></constructor-arg>
<constructor-arg type="double" value="25.5"></constructor-arg>
<constructor-arg type="int" value="10"></constructor-arg>
<constructor-arg type="int" value="20"></constructor-arg>
<!-- 3、按索引匹配 如果属性过多,匹配会非常麻烦 -->
<constructor-arg index="0" value="Hello Kgc Spring!"></constructor-arg>
<constructor-arg index="2" value="25.5"></constructor-arg>
<constructor-arg index="3" value="10"></constructor-arg>
<constructor-arg index="1" value="20"></constructor-arg>
<!-- 4、按名称匹配 推荐使用 -->
<constructor-arg name="message" value="Hello Kgc Spring!"></constructor-arg>
<constructor-arg name="f" value="25.5"></constructor-arg>
<constructor-arg name="i" value="10"></constructor-arg>
<constructor-arg name="age" value="20"></constructor-arg>
// 2、演示构造方法注入
// 问题:
// 如果有多个参数怎么办? 写多个 <constructor-arg>
// 1、默认是按顺序匹配
// 2、按类型匹配 如果有相同类型
// 3、按索引匹配 如果属性过多,匹配会非常麻烦
// 4、按名称匹配 spring3 引进 按构造方法中的名称匹配 ,而不是属性名称匹配
public ConstractDemo(){}
public ConstractDemo(String message){
System.out.println("这确实是构造方法注入1="+this.message);
this.message = message;
System.out.println("这确实是构造方法注入2="+this.message);
}
public ConstractDemo(String message, int i, double f, int age) {
this.message = message;
this.i = i;
this.f = f;
this.age = age;
}
> P命名空间注入
<bean id="constractDemo" class="com.kgc.ios.inject.ConstractDemo"
p:message="Hello Kgc Spring!"
></bean>
// 1、Setter 方法注入 3.P命名空间注入也需要setter方法 p:属性名="值"
public void setMessage(String message) {
this.message = message;
}
》注入类型
几种类型注入
> 注入直接量
* 使用<value> 标签实现
* 注意特殊字符的处理
> 引用 Bean
* 使用 <ref> 标签实现
<bean id="a" class="com.kgc.ioc.type.A">
<property name="b" ref="api" ></property>
</bean>
ref 引用需要注入的 Bean 的名字,除了以上这种写法,还要下面一种写法
<bean id="a" class="com.kgc.ioc.type.A">
<property name="b">
<ref bean="api" />
</property>
</bean>
> 使用 内部Bean
* 内部 bean 可以没有 id 和 name
* <property name="dao">
<bean class="dao.impl.UserDao"/> </property>
<bean id="a" class="com.kgc.ioc.type.A">
<property name="b">
<!-- 内部bean 可以没有id和name 哪怕设置了 id 和 name 也不起作用 -->
<bean class="com.kgc.ioc.type.B"></bean>
</property>
<property name="message" ><null/></property>
</bean>
> 注入集合类型属性
* 分别使用<list>、<set>、<map>、<props> 标签实现
> list 直接量注入 -- 引用 bean 注入
private List<String> strs = new ArrayList<String>();
private List<Api> apis = new ArrayList<Api>();
public void setStrs(List<String> strs) {
this.strs = strs;
}
public void setApis(List<Api> apis) {
this.apis = apis;
}
通过<ref> 标签 获得bean 对象
<bean id="injectListDemo" class="com.kgc.ioc.type.collection.InjectListDemo" >
<property name="strs">
<list>
<value>盛</value>
<value>世</value>
<value>龙</value>
<value>腾</value>
</list>
</property>
<property name="apis">
<list>
<ref bean="api01"/>
<ref bean="api02"/>
</list>
</property>
</bean>
> set 直接量注入 -- 引用 bean 注入
private Set<String> sets = new HashSet<String>();
private Set<Api> apiSet = new HashSet<Api>();
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void setApiSet(Set<Api> apiSet) {
this.apiSet = apiSet;
}
<bean id="injectListDemo" class="com.kgc.ioc.type.collection.InjectListDemo" >
<property name="sets">
<set>
<value>盛</value>
<value>世</value>
<value>龙</value>
<value>腾</value>
</set>
</property>
<property name="apiSet">
<set>
<ref bean="api01"/>
<ref bean="api02"/>
</set>
</property>
</bean>
>map map有四种情况
private Map< String,String> mapStr = new HashMap<String,String>();
private Map< String,Api> mapApi = new HashMap<String,Api>();
public void setMapStr(Map<String, String> mapStr) {
this.mapStr = mapStr;
}
public void setMapApi(Map<String, Api> mapApi) {
this.mapApi = mapApi;
}
public static void main(String[] args) {
ApplicationContext atc = new ClassPathXmlApplicationContext("applicationContext-type2.xml");
InjectMapDemo ild= (InjectMapDemo)atc.getBean("injectMapDemo");
// 获取map 集合中所有的key
Set<String> keys = ild.mapStr.keySet();
for (String key : keys) {
// 根据key 取出对应的value
System.out.println("key = "+key+" - value = "+ild.mapStr.get(key));
}
System.out.println("======================================");
// 直接循环map 里所有value的值
for (Api api : ild.mapApi.values()) {
api.run();
}
通过 value-ref 可以 拿到 bean 中的对象 还有注意是<entry>
<!-- 演示Map 注入 -->
<bean id="injectMapDemo" class="com.kgc.ioc.type.collection.InjectMapDemo">
<property name="mapStr">
<map>
<entry key="kgc1" value="v1" />
<entry key="kgc2" value="v2" />
<entry key="kgc3" value="v3" />
</map>
</property>
<property name="mapApi">
<map>
<entry key="kgc1" value-ref="api01"/>
<entry key="kgc2" value-ref="api02"/>
</map>
</property>
</bean>
>Properties 注入
Properties steP = new Properties();
public void setSteP(Properties steP) {
this.steP = steP;
}
public static void main(String[] args) {
ApplicationContext atc = new ClassPathXmlApplicationContext("applicationContext-type2.xml");
InjectProperties ip = (InjectProperties)atc.getBean("injectProperties");
Set<Entry<Object,Object>> entrySet = ip.steP.entrySet();
Iterator it = entrySet.iterator();
while(it.hasNext()){
Entry<Object,Object> e = (Entry<Object,Object>)it.next();
System.out.println(e.getKey()+"-"+e.getValue());
}
}
没有引用 bean
<!-- 演示Properties 注入 -->
<bean id="injectProperties" class="com.kgc.ioc.type.collection.InjectProperties">
<property name="steP">
<props>
<prop key="kgc1">v1</prop>
<prop key="kgc2">v2</prop>
<prop key="kgc3">v3</prop>
</props>
</property>
</bean>
>merge 实现的效果是 将两个表中的值 合并 为一个集合
// MargeA
private List<String> listA = new ArrayList<String>();
public void setListA(List<String> listA){
this.listA = listA;
}
//MargeB
private List<String> listA = new ArrayList<String>();
public void setListA(List<String> listA) {
this.listA = listA;
}
public static void main(String[] args) {
ApplicationContext atc = new ClassPathXmlApplicationContext("applicationContext-type2.xml");
MergeB b = (MergeB)atc.getBean("mergeB");
for(String str : b.listA){
System.out.println(str);
}
}
1.两个表需要建立父子关系 -》 2.父类填入属性 abstrac="true" -》 3. 继承类(最后合并输出的是该类)填入属性 parent="mergeA" -》 4. 继承类 <list> 标签中 添加属性 merge="ture" 表示添加并合并 父类集合
注: 1、标明父子 bean 关系
2、希望合并的集合名称要是一样的
3、指定 merge = true
<!-- 演示Merge -->
<bean abstract="true" id="mergeA" class="com.kgc.ioc.type.merge.MergeA">
<property name="listA">
<list>
<value>kgc1</value>
<value>kgc2</value>
</list>
</property>
</bean>
<bean id="mergeB" parent="mergeA" class="com.kgc.ioc.type.merge.MergeB">
<property name="listA">
<!-- 这边merge="true" 别忘了 -->
<list merge="true">
<value>kgc3</value>
<value>kgc4</value>
</list>
</property>
</bean>
> 注入null 和 空字符串值
* 使用<null/> 注入 null值
* 使用 <value></value> 注入空字符串值
》集合注入的应用场景
1、JDBC 的配置(需要key-value)
2、托管的 Filter (校验器)
例如:单点登录
3、覆盖配置
1.在应用之初会初始化一些 配置文件
2.用自己独立的配置文件覆盖替换原有文件
上一篇: 我只是不想要解释
下一篇: 背面的戈壁上还有一只卧*