欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring IoC (二)

程序员文章站 2022-06-01 13:05:45
...

》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;
	}

Spring IoC (二)

 》注入类型

几种类型注入

>   注入直接量

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

 

相关标签: Spring 依赖注入