首页IT科技springioc怎么管理bean(day04-Spring管理Bean-IOC-02)

springioc怎么管理bean(day04-Spring管理Bean-IOC-02)

时间2025-05-04 07:58:31分类IT科技浏览3314
导读:Spring管理Bean-IOC-02 2.基于XML配置bean...

Spring管理Bean-IOC-02

2.基于XML配置bean

2.7通过util空间名称创建list

BookStore.java:

package com.li.bean; import java.util.List; /** * @author 李 * @version 1.0 */ public class BookStore { private List<String> bookList; //如果类中没有其他构造器           ,默认构造器可以不写 // 如果有其他构造器                 ,则必须显示定义无参构造器 public BookStore() { } public List<String> getBookList() { return bookList; } public void setBookList(List<String> bookList) { this.bookList = bookList; } @Override public String toString() { return "BookStore{" + "bookList=" + bookList + }; } }

如果有多个BookStore对象    ,list的内容都一样        ,按照之前的做法                  ,每一个list都要写上相同的value值           。但使用util命名空间可以达到数据复用的效果                 。

beans.xml:

<!--定义util:list,并指定id       ,可以达到数据复用的效果--> <util:list id="myBookList"> <value>三国演义</value> <value>红楼梦</value> <value>西游记</value> <value>水浒传</value> </util:list> <!--配置BookStores对象--> <bean class="com.li.bean.BookStore" id="bookStore"> <property name="bookList" ref="myBookList"/> </bean>

注意引入util命名空间     ,一般来说ide会有提示                  ,如果没有则按如下引入:

SpringBeanTest:

package com.li.test; import com.li.bean.BookStore; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; /** * @author 李 * @version 1.0 */ public class SpringBeanTest { //使用util:list名称空间给属性赋值 @Test public void setBeanByUtilList() { ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); BookStore bookStore = ioc.getBean("bookStore", BookStore.class); System.out.println("bookStore=" + bookStore); } }

2.8级联属性赋值

案例说明:spring的ioc容器          ,可以直接给对象属性的属性赋值  ,即级联属性赋值

完成步骤:

(1)创建Dept.java和Emp.java

(2)配置beans.xml

Dept.java:

package com.li.bean; /** * @author 李 * @version 1.0 * 部门类 */ public class Dept { private String name; public Dept() { } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Dept{" + "name=" + name + \ + }; } }

Emp.java:

package com.li.bean; /** * @author 李 * @version 1.0 * 员工类 */ public class Emp { private String name; private Dept dept; public Emp() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } @Override public String toString() { return "Emp{" + "name=" + name + \ + ", dept=" + dept + }; } }

beans.xml:

<!--配置Dept对象--> <bean class="com.li.bean.Dept" id="dept"/> <!--配置Emp对象--> <bean class="com.li.bean.Emp" id="emp"> <property name="name" value="jack"/> <property name="dept" ref="dept"/> <!--这里我希望给dept的name属性赋值[级联属性赋值]--> <property name="dept.name" value="Java开发部门"/> </bean>

SpringBeanTest:

package com.li.test; import com.li.bean.Emp; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; /** * @author 李 * @version 1.0 */ public class SpringBeanTest { //使用级联赋值给属性的属性赋值 @Test public void setBeanByRelation() { ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); Emp emp = ioc.getBean("emp", Emp.class); System.out.println("emp=" + emp); } }

2.9通过静态工厂获取对象

在spring的ioc容器                 ,可以通过静态工厂获取bean对象

完成步骤:

(1)静态工厂类MyStaticFactory类和Monster类

(2)配置beans.xml

Monster类详见上一篇--2.1通过类型来获取bean

MyStaticFactory.java:

package com.li.factory; import com.li.bean.Monster; import java.util.HashMap; import java.util.Map; /** * @author 李 * @version 1.0 * 静态工厂类-可以返回Monster对象 */ public class MyStaticFactory { private static Map<String, Monster> monsterMap; //使用static静态代码块进行初始化 // (静态代码块在类加载的同时就直接执行             ,且只执行一次) static { monsterMap = new HashMap<>(); monsterMap.put("monster01", new Monster(100, "孙悟空", "七十二变")); monsterMap.put("monster02", new Monster(200, "金蝉子", "普渡众生")); } //提供一个方法,返回monster对象 public static Monster getMonster(String key) { return monsterMap.get(key); } }

beans.xml:

<!--配置monster,通过静态工厂获取 1.通过静态工厂配置bean 2.class不再是monster的路径              ,而是静态工厂的全路径 3.factory-method 表示指定静态工厂的哪个方法来返回对象 4.constructor-arg value="monster02" 指定要返回静态工厂的哪个对象 --> <bean id="my_monster01" class="com.li.factory.MyStaticFactory" factory-method="getMonster"> <constructor-arg value="monster02"/> </bean>

SpringBeanTest:

package com.li.test; import com.li.bean.Monster; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; /** * @author 李 * @version 1.0 */ public class SpringBeanTest { //使用静态工厂来获取 bean @Test public void getBeanByStaticFactory() { ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); Monster my_monster01 = ioc.getBean("my_monster01", Monster.class); //这里如果使用的是相同id获取bean                ,那么获取的实际上是同一个对象,例如: Monster my_monster001 = ioc.getBean("my_monster01", Monster.class); // 因为静态工厂中的静态代码块只执行一次  ,这里不同的对象引用指向的都是同一个对象 System.out.println(my_monster01 == my_monster001);//true System.out.println("my_monster01=" + my_monster01); } }

2.10通过实例工厂获取对象

Monster类详见上一篇--2.1通过类型来获取bean

MyInstanceFactory:

package com.li.factory; import com.li.bean.Monster; import java.util.HashMap; import java.util.Map; /** * @author 李 * @version 1.0 * 实例工厂类 */ public class MyInstanceFactory { private Map<String, Monster> monster_map; //通过普通代码块进行初始化 //普通代码块每创建一个对象就会执行一次 { monster_map = new HashMap<>(); monster_map.put("monster03", new Monster(300, "猪八戒", "九尺钉耙")); monster_map.put("monster04", new Monster(400, "沙和尚", "丈二禅杖")); } //写一个方法返回Monster对象 public Monster getMonster(String key) { return monster_map.get(key); } }

beans.xml:

<!--因为是实例工厂对象           ,所以需要配置才能使用(静态工厂可以直接使用不用配置)--> <bean class="com.li.factory.MyInstanceFactory" id="myInstanceFactory"/> <bean class="com.li.factory.MyInstanceFactory" id="myInstanceFactory02"/> <!--配置monster,通过实例工厂获取 1.factory-bean 表示使用哪个实例工厂对象返回bean 2.factory-method 指定使用实例工厂对象的哪个方法返回bean 3.constructor-arg value="monster03" 指定获取实例工厂中的哪个对象 --> <bean id="my_monster02" factory-bean="myInstanceFactory" factory-method="getMonster"> <constructor-arg value="monster03"/> </bean> <bean id="my_monster03" factory-bean="myInstanceFactory02" factory-method="getMonster"> <constructor-arg value="monster03"/> </bean>

SpringBeanTest:

package com.li.test; import com.li.bean.Monster; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; /** * @author 李 * @version 1.0 */ public class SpringBeanTest { //使用实例工厂来获取 bean @Test public void getBeanByInstanceFactory() { ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); Monster my_monster02 = ioc.getBean("my_monster02", Monster.class); System.out.println("my_monster02=" + my_monster02); // 这里使用相同的id获取bean                 ,那么返回的对象也是同一个!! Monster my_monster002 = ioc.getBean("my_monster02", Monster.class); // 因为虽然是实例工厂    ,但是两次 ioc.getBean("my_monster02", Monster.class)使用的都是 // 同一个工厂实例(id="myInstanceFactory")        ,返回的自然也就是同一个实例工厂中的 monster System.out.println(my_monster02 == my_monster002);//true //换而言之                  ,如果不是同一个实例工厂       ,那么返回的就不是同一个对象了 //(这里的my_monster03     ,在beans.xml使用的是 id=myInstanceFactory02的实例工厂) Monster my_monster03 = ioc.getBean("my_monster03", Monster.class); System.out.println("my_monster03=" + my_monster03); System.out.println(my_monster02 == my_monster03);//false } }

2.11通过FactoryBean获取对象(重点)

在spring的ioc容器                  ,通过FactoryBean获取bean对象

MyFactoryBean:

package com.li.factory; import com.li.bean.Monster; import org.springframework.beans.factory.FactoryBean; import java.util.HashMap; import java.util.Map; /** * @author 李 * @version 1.0 * FactoryBean */ public class MyFactoryBean implements FactoryBean<Monster> { //这个就是你配置的时候          ,指定要获取的对象对应的key private String key; private Map<String, Monster> monster_map; //代码块完成初始化 { monster_map = new HashMap<>(); monster_map.put("monster05", new Monster(5, "黑风怪", "翻江倒海")); monster_map.put("monster06", new Monster(6, "金角大王", "超能力")); } public void setKey(String key) { this.key = key; } @Override public Monster getObject() throws Exception { return monster_map.get(key); } @Override public Class<?> getObjectType() { return Monster.class; } @Override public boolean isSingleton() {//这里指定是否是单例对象 return true; } }

beans.xml:

<!--配置monster对象  ,通过FactoryBean来获取 1.这里的class 指定要使用的FactoryBean 2.key是 你设置的FactoryBean的属性key 3.value 就是你要获取的对象的对应 key --> <bean id="my_monster05" class="com.li.factory.MyFactoryBean"> <property name="key" value="monster05"/> </bean>

SpringBeanTest:

package com.li.test; import com.li.bean.Monster; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; /** * @author 李 * @version 1.0 */ public class SpringBeanTest { //通过FactoryBean获取bean对象 @Test public void getBeanByFactoryBean() { ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); Monster my_monster05 = ioc.getBean("my_monster05", Monster.class); System.out.println("my_monster05=" + my_monster05); } }

2.12bean配置信息重用(继承)

在spring的ioc容器中                 ,提供了一种继承的方式来实现bean配置信息的重用

beans.xml:

<!--配置Monster对象--> <bean class="com.li.bean.Monster" id="monster10"> <property name="monsterId" value="10"/> <property name="name" value="蜈蚣精"/> <property name="skill" value="蜇人"/> </bean> <!--现在配置另一个Monster对象             , 1.这个对象的属性值 和 id="monster10"对象属性一样 2.parent="monster10" 指定当前这个配置的对象的属性值从id=monster10的对象来 --> <bean id="monster11" class="com.li.bean.Monster" parent="monster10"/>

SpringBeanTest:

package com.li.test; import com.li.bean.Monster; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; /** * @author 李 * @version 1.0 */ public class SpringBeanTest { //配置Bean(通过继承) @Test public void getBeanByFactoryBean() { ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); Monster monster10 = ioc.getBean("monster10", Monster.class); Monster monster11 = ioc.getBean("monster11", Monster.class); System.out.println("monster10=" + monster10); System.out.println("monster11=" + monster11); } }

注意:

如果bean指定了abstract="true" 表示该bean对象是只用于被继承的

那么这个bean就不能被获取/实例化

此时如果输出monster10,就会显示错误:

2.13bean创建顺序

在spring的ioc容器              ,默认是按照配置的顺序创建bean对象    。比如:

<bean id="student01" class="com.hspedu.bean.Student" /> <bean id="department01" class="com.hspedu.bean.Department" />

会先创建 student01 这个 bean 对象                ,然后创建 department01 这个 bean 对象

但如果这样配置:

<bean id="student01" class="com.hspedu.bean.Student" depends-on="department01"/> <bean id="department01" class="com.hspedu.bean.Department" />

会先创建 department01 对象  ,再创建 student01 对象.

例子

Student:

package com.li.bean; /** * @author 李 * @version 1.0 */ public class Student { public Student() { System.out.println("Student 构造器被执行..."); } }

Department:

package com.li.bean; /** * @author 李 * @version 1.0 */ public class Department { public Department() { System.out.println("Department 构造器被执行..."); } }

beans.xml:

<!--测试 bean对象的创建顺序--> <bean id="student01" class="com.li.bean.Student"/> <bean id="department01" class="com.li.bean.Department"/>

测试类:

//测试 Bean的创建顺序 @Test public void testBeanByCreate() { ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); System.out.println("ok~"); }

如果我们在配置student01对象时           ,加上depends-on="department01"                 ,spring就会认为你的student01对象时依赖于department01对象    ,会先创建department01对象        。

<bean id="student01" class="com.hspedu.bean.Student" depends-on="department01"/> <bean id="department01" class="com.hspedu.bean.Department" />

总结:在默认情况下        ,bean创建的顺序是按照默认配置顺序来的                  。但是如果我们在对象配置中指定了依赖对象                  ,就会先创建被依赖的对象       。

一个问题?

1.先看下面的配置       ,请问两个bean创建的顺序是什么?并分析执行流程

<!--配置MemberDAOImpl对象--> <bean class="com.li.dao.MemberDAOImpl" id="memberDAOImpl"/> <bean class="com.li.service.MemberServiceImpl" id="memberServiceImpl"> <property name="memberDAO" ref="memberDAOImpl"/> </bean>

(1)先创建 id=memberDaoImpl 的对象

(2)再创建 id=memberServiceImpl 的对象

(3)调用 memberServiceImpl.setMemberDAO() 方法     ,完成引用

2.先看下面的配置                  ,请问两个bean创建的顺序是什么?并分析执行流程

<bean class="com.li.service.MemberServiceImpl" id="memberServiceImpl"> <property name="memberDAO" ref="memberDAOImpl"/> </bean> <!--配置MemberDAOImpl对象--> <bean class="com.li.dao.MemberDAOImpl" id="memberDAOImpl"/>

(1)先创建 id=memberServiceImpl 的对象

(2)再创建 id=memberDaoImpl 的对象

(3)调用 memberServiceImpl.setMemberDAO() 方法          ,完成引用

总结:ioc容器会把整个bean的创建当做一个整体来对待  ,会把配置文件中所有对象bean先创建好                 ,然后才完成对象间的引用     。

见2.4

2.14bean对象的单例和多例

在spring的ioc容器中             ,默认是按照单例创建的,即配置一个bean对象后              ,ioc容器只会创建一个bean实例                  。

如果希望ioc容器配置的某个bean对象                ,是以多个实例形式创建的  ,可以通过配置scope="prototype"来指定          。

例子1-单例对象

Cat:

package com.li.bean; /** * @author 李 * @version 1.0 */ public class Cat { private Integer id; private String name; public Cat() { System.out.println("Cat() 构造器被执行..."); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

beans.xml:

<!--配置 Cat对象 1.默认情况下           ,scope属性的值为 "singleton"                 ,即ioc容器中只会有一个这样的bean对象 当执行getBean时    ,返回的是同一个对象 2.如果希望每次使用getBean都返回新的Bean对象        ,就要把scope的属性设为 prototype --> <bean id="cat" class="com.li.bean.Cat"> <property name="id" value="10"/> <property name="name" value="小花猫"/> </bean>

测试类:

//测试Scope @Test public void testBeanScope() { ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); Cat cat1 = ioc.getBean("cat", Cat.class); Cat cat2 = ioc.getBean("cat", Cat.class); Cat cat3 = ioc.getBean("cat", Cat.class); System.out.println("cat1="+cat1); System.out.println("cat2="+cat2); System.out.println("cat3="+cat3); }

输出如下:地址值相同                  ,证明这三个对象引用都指向了同一个对象

例子2-多例对象

现在我们把例子1的cat对象的配置改为scope="prototype"

<bean id="cat" class="com.li.bean.Cat" scope="prototype"> <property name="id" value="10"/> <property name="name" value="小花猫"/> </bean>

输出如下:构造器执行了三次       ,说明创建了三个Cat对象(对象的地址值也不一样)

使用细节

当bean为scope="singleton"(默认值)     ,在启动容器时                  ,就会创建单例对象          ,并放入singletonObjects集合

当bean设置为scope="prototype"  ,即设置为多实例机制后                 ,该bean是在getBean时才创建

如果是单例singleton             ,但又希望在getBean时才创建,可以指定懒加载lazy-init="true" (默认值是false)

通常情况下              ,lazy-init 使用默认值false                ,因为在开发看来  ,用空间换时间是值得的           ,除非有特殊要求  。

如果scope="prototype"                 ,这时你的lazy-init属性值不管设置为什么    ,都默认为true

因为多例情况下        ,spring无法知道创建几个对象                  ,因此只有在用到的时候才能创建

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
文章生成器是什么(AI原创文章生成器-让你轻松批量生成高质量文章) 如何用公积金贷款买房(公积金贷款额度是多少)