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.用自己独立的配置文件覆盖替换原有文件

猜你喜欢

转载自blog.csdn.net/qq_41902618/article/details/81486433