spring配置和管理bean
Spring 管理 Bean-IOC
在 beans.xml 中,我们注入 2 个 Monster 对象, 但是不指定 id
<bean class="com.hspedu.spring.beans.Monster" > <property name="monsterId" value="1010"/> <property name="name" value="张三~"/> <property name="skill" value="呼呼~"/> </bean> <bean class="com.hspedu.spring.beans.Monster"> <property name="monsterId" value="666"/> <property name="name" value="里斯~~!!"/> <property name="skill" value="giao~~"/> </bean>
问题 1:运行会不会报错
答:不会报错,会正常运行
问题 2:如果不报错, 你能否找到分配的 id, 并获得到该对象.
答:系统会默认分配 id ,分配 id 的规则是 全类名#0 , 全类名#1 这样的规则来分配 id, 我们可以通过 debug 方式来查看
Bean 管理包括两方面——创建 bean 对象 和 给 bean 注入属性
Bean 配置方式包括两方面 —— 基于 xml 文件配置方式 和 基于注解方式
基于 XML 配置 bean
通过类型来获取 bean
细节说明:
1. 按类型来获取 bean, 要求 ioc 容器中的同一个类的 bean 只能有一个, 否则会抛出异常NoUniqueBeanDefinitionException
2. 这种方式的应用场景:比如 XxxAction/Servlet/Controller, 或 XxxService 在一个线程中只需要一个对象实例(单例)的情况
3. 在容器配置文件(比如 beans.xml)中给属性赋值, 底层是通过setter 方法完成的, 这也是为什么我们需要提供 setter 方法
<!--解读: 1.beans.xml中可以配置多个bean(一个bean标签表示一个Java对象),这里配置一个hero对象的JavaBean 2.class属性写类的全路径 => 用于spring底层反射创建对象 3.<bean class="com.recorder.spring.bean.Hero" id="hero01"> id表示该bean对象在spring容器中的id,可以通过id获取容器中的对象 4.<property name="id" value="1"></property> value用于给对象的实行赋值 -->
通过构造器来配置 bean
因为类不可能有完全相同类型和顺序的构造器,所以可以通过type来指定
<!-- 在 spring 的 ioc 容器, 可以通过构造器来配置 bean 对象 --> <bean class="com.recorder.spring.bean.Hero" id="hero03"> <!--1.下标方式--> <!--这里的index表示构造器的第几个参数,从0开始计算 除了index还可以通过name和type来配置--> <constructor-arg value="3" index="0"></constructor-arg> <constructor-arg value="刘备" index="1"></constructor-arg> <constructor-arg value="仁德" index="2"></constructor-arg> </bean> <bean class="com.recorder.spring.bean.Hero" id="hero04"> <!--2.数据类型方式--> <constructor-arg value="诸葛亮" type="java.lang.String"/> </bean> <bean class="com.recorder.spring.bean.Hero" id="hero004"> <!--2.name类型方式--> <constructor-arg value="3" name="id"/> <constructor-arg value="神诸葛亮" name="name"/> <constructor-arg value="七星" name="skill"/> </bean>
使用细节
1. 通过 index 属性来区分是第几个参数
2. 通过 type 属性来区分是什么类型(按照顺序)
通过 p 名称空间配置 bean
<!--通过p命名空间来创建--> <!--将光标放在p , 输入alt+enter , 就会自动的添加xmlnamesapce--> <bean class="com.recorder.spring.bean.Hero" id="hero05" p:id="5" p:name="吕布" p:skill="无双" />
通过 ref 来实现 bean 对象的相互引用(体现依赖注入——一个属性依赖于另一个属性)
<!--通过 ref 来实现 bean 对象的相互引用--> <!-- bean 对象的相互引用 1. 其它含义和前面一样 2. ref 表示 memberDAO 这个属性将引用/指向 id = memberDAOImpl 对象 3.注意在spring容器中,是作为一个整体来执行的,引用bean对象时对配置的顺序没有要求(所以这里将vmemberDAO放到MemberServiceImpl后面配置也没有问题,但建议按照顺序写来保证阅读方便)--> <bean class="com.recorder.spring.dao.MemberDAOImpl" id="memberDAO"/> <bean class="com.recorder.spring.service.MemberServiceImpl" id="memberService"> <property name="memberDAO" ref="memberDAO"/> </bean>
通过观察容器结构也可以确定
引用/注入内部 bean 对象
<!--也可以通过内部bean的方式--> <bean class="com.recorder.spring.service.MemberServiceImpl" id="memberService2"> <property name="memberDAO"> <bean class="com.recorder.spring.dao.MemberDAOImpl" id="memberDAO"/> </property> </bean>
这里不再是引用外部的bean对象,而是直接在自己的内部配置一个内部bean
引用/注入集合/数组类型
<!--配置master bean--> <bean class="com.recorder.spring.bean.Master" id="master"> <property name="name"> <value>紫英</value> </property> <property name="heroList"> <!--配置list--> <list> <!--可以使用ref依赖--> <ref bean="hero01"></ref> <ref bean="hero02"></ref> <!--也可以直接使用内部bean--> <bean class="com.recorder.spring.bean.Hero"> <property name="id" value="6"></property> <property name="name" value="赵云"></property> <property name="skill" value="龙胆"></property> </bean> </list> </property> <!--配置map属性--> <property name="heroMap"> <!--先来个map标签--> <map> <!--map中配置各个entry--> <entry> <!--entry中配置对应的key和value--> <key> <!--意思是key的值是hero03--> <value>hero03</value> </key> <!--value的值,可以使用依赖或者内部bean--> <ref bean="hero03"></ref> </entry> <entry> <key> <value>hero04</value> </key> <ref bean="hero04"></ref> </entry> </map> </property> <!--给set赋值--> <property name="heroSet"> <!--跟list差不多,这里使用ref引用--> <set> <ref bean="hero01"></ref> <bean class="com.recorder.spring.bean.Hero"> <property name="id" value="7"></property> <property name="name" value="貂蝉"></property> <property name="skill" value="离间"></property> </bean> </set> </property> <!--给数组赋值--> <property name="heroName"> <array> <!--array标签中直接使用value还是其他要看数组的类型, 如果是引用类型可以使用bean或者ref--> <value>along</value> <value>小丁猫</value> </array> </property> <!--给properties属性赋值--> <!--注意properties的key和v都是string类型的--> <property name="pros"> <props> <prop key="username">root</prop> <prop key="password">123456</prop> <prop key="ip">192.168.66.66</prop> </props> </property> </bean>
Master{name='紫英', HeroList=[Hero{id=1, name='李白', skill='青莲剑歌'}, Hero{id=2, name='韩信', skill='国士无双'}, Hero{id=6, name='赵云', skill='龙胆'}], HeroMap={hero03=Hero{id=3, name='刘备', skill='仁德'}, hero04=Hero{id=null, name='诸葛亮', skill='null'}}, HeroSet=[Hero{id=1, name='李白', skill='青莲剑歌'}, Hero{id=7, name='貂蝉', skill='离间'}], HeroName=[along, 小丁猫], pros={password=123456, ip=192.168.66.66, username=root}}
使用细节
1. 主要掌握 List/Map/Properties 三种集合的使用.
2. Properties 集合的特点:
1) 这个 Properties 是 Hashtable 的子类 , 是 key-value 的形式
2) key 是 string 而 value 也是 string
通过 util 名称空间创建 list
<!--通过util:list命名空间来实现数据复用--> <util:list id="myBookList"> <value>西游记</value> <value>水浒传</value> <value>红楼梦</value> <value>三国演义</value> </util:list>
//优点————如果有别的bean使用这个booklist就可以直接引用,实现数据复用和共享
<bean class="com.recorder.spring.bean.BookStore" id="bookStore"> <property name="bookList" ref="myBookList"/> </bean>
级联属性赋值
spring 的 ioc 容器, 可以直接给对象属性的属性赋值, 即级联属性赋值
dept:部门 emp:职员
<!--通过级联属性赋值--> <bean class="com.recorder.spring.bean.Dept" id="dept"></bean> <bean class="com.recorder.spring.bean.Emp" id="emp"> <property name="name" value="along"></property> <property name="dept" ref="dept"></property> <!--这里底层会调用dept对象的setName方法去赋值--> <property name="dept.name" value="java开发"></property> </bean>
通过静态工厂获取对象
先创建一个静态工厂
public class MyStaticFactory { //静态代码块——随着类的加载而加载,并且只执行一次 private static Map<String, Hero> heroMap; //通过静态代码块进行初始化 static { heroMap = new HashMap<>(); heroMap.put("hero001",new Hero(1,"孙悟空","金箍棒")); heroMap.put("hero002",new Hero(2,"猪八戒","九齿钉耙")); } public static Hero getHero(String key){ return heroMap.get(key); } }
配置xml文件
<!--通过静态工厂获取hero/配置bean 解读: 1.class的路径不是hero的而是静态工厂类的 2.factory-method表示返回hero对象的静态工厂类的方法 3.constructor-arg value="hero001" value表示返回静态工厂类的哪个对象 --> <bean class="com.recorder.spring.factory.MyStaticFactory" id="my_hero01" factory-method="getHero"> <constructor-arg value="hero001"></constructor-arg> </bean>
通过实例工厂获取对象
先创建一个实例工厂类
import com.recorder.spring.bean.Hero; import java.util.HashMap; import java.util.Map; /** * @author 紫英 * @version 1.0 * @discription 实例工厂类——可以创建或返回hero对象 */ public class MyInstanceFactory { private Map<String, Hero> heroMap; //通过普通代码块进行初始化——每创建一个MyInstanceFactory实例普通代码块接会被执行一次 //但是在配置文件中同一个id在容器中就对应着同一个实例工厂,所以是同一个对象, // 不同id的情况下就不是同一个对象 { heroMap = new HashMap<>(); heroMap.put("hero003", new Hero(3, "孙悟空~~", "金箍棒~~")); heroMap.put("hero004", new Hero(4, "猪八戒~~", "九齿钉耙~~")); } public Hero getHero(String key) { return heroMap.get(key); } }
配置xml文件
<!--先配置一个实例工厂对象——因为静态类不用创建实例就可以调用方法,普通类则不行--> <bean class="com.recorder.spring.factory.MyInstanceFactory" id="myInstanceFactory"/> <!--通过实例工厂获取hero/配置bean 解读: 1.factory-bean表示指定哪个实例工厂 2.factory-method表示返回hero对象的实例工厂类的方法 3.constructor-arg value="hero004" value表示返回实例工厂类的哪个对象 --> <bean id="my_hero02" factory-bean="myInstanceFactory" factory-method="getHero"> <constructor-arg value="hero004"></constructor-arg> </bean>
通过 FactoryBean 获取对象(重点)
package com.recorder.spring.factory; import com.recorder.spring.bean.Hero; import org.springframework.beans.factory.FactoryBean; import java.util.HashMap; import java.util.Map; /** * @author 紫英 * @version 1.0 * @discription 通过 FactoryBean 获取对象(重点) */ public class MyFactoryBean implements FactoryBean<Hero> { private String key;//配置xml文件时,指定要获取的对象的key public void setKey(String key) { this.key = key; } private Map<String,Hero> heroMap; { heroMap = new HashMap<>(); heroMap.put("hero003", new Hero(3, "孙悟空~~", "金箍棒~~")); heroMap.put("hero004", new Hero(4, "猪八戒~~", "九齿钉耙~~")); } @Override public Hero getObject() throws Exception { return heroMap.get(key); } @Override public Class<?> getObjectType() { return Hero.class; } @Override //返回的是否是单例对象 public boolean isSingleton() { return true; } }
配置xml文件
<!--通过FactoryBean配置hero对象--> <bean id="my_hero03" class="com.recorder.spring.factory.MyFactoryBean"> <!--这里的key就是MyFactoryBean中的属性key--> <property name="key" value="hero003"></property> </bean>
bean 配置信息重用(继承)
<!--bean的继承(复用) abstract="true"表示该bean只能被继承,不能被实例化,否则会报错--> <bean class="com.recorder.spring.bean.Hero" id="hero06" abstract="true"> <!--1.下标方式--> <property name="id" value="6"></property> <property name="name" value="曹仁"></property> <property name="skill" value="解围"></property> </bean> <!--parent="hero06"表示id为hero07的bean的属性继承自hero06--> <bean class="com.recorder.spring.bean.Hero" id="hero07" parent="hero06"/>
本文来自博客园,作者:紫英626,转载请注明原文链接:https://www.cnblogs.com/recorderM/p/16799412.html