Spring 管理 Bean-IOC--基于 XML 配置bean

news/2025/3/10 6:15:25/

目录

Spring 管理 Bean-IOC--基于 XML 配置bean

Spring 配置/管理 bean 介绍

Bean 管理包括两方面

Bean 配置方式

基于 XML 配置 bean

通过 spring 的ioc 容器, 获取一个bean 对象

获取 bean 的方式:按类型

 Monster类

 注意

 xml配置

细节说明

通过构造器配置 bean 

xml配置

使用细节

通过 p 名称空间配置 bean

 xml配置

引用/注入其它 bean 对象--ref

 MemberDAOImpl

 MemberServiceImpl 

 xml配置

 引用/注入内部 bean 对象--内部 bean 对象

  xml配置

引用/注入集合/数组类型

在 spring 的 ioc 容器, 看看如何给 bean

Master.java 

 配置 beans.xml

setCollectionByPro 

通过 util 名称空间创建 list

创建BookStore 类

修改 beans.xml , 增加配置

级联属性赋值

创建Dept.java

创建Emp.java

修改 beans.xml

通过静态工厂获取对象

MyStaticFactory类

修改 beans.xml 

通过实例工厂获取对象

MyInstanceFactory 类 

修改 beans.xml

通过 FactoryBean 获取对象

创建 MyFactoryBean  

配置beans.xml

bean 配置信息重用(继承)

 配置beans.xml

bean 创建顺序

 配置beans.xml 

bean 对象的单例和多例

● 说明

创建car.java 

 配置beans.xml

使用细节

 bean 的生命周期

● 说明:

创建House.java

 配置beans.xml 

 使用细节

配置 bean 的后置处理器

 说明

创建后置处理器MyBeanPostProcessor.java

 配置beans.xml 

其它说明

通过属性文件给 bean 注入值 

src/ 创建 my.properties

 配置beans.xml  

基于 XML 的 bean 的自动装配

OrderDao

OrderService

OrderAction  

  配置beans.xml 

spring eel 表达式

 SpELBean.java

  配置beans.xml  

测试


Spring 管理 Bean-IOC--基于 XML 配置bean

Spring 配置/管理 bean 介绍

Bean 管理包括两方面

        创建 bean 对象

        给 bean 注入属性

Bean 配置方式

        基于 xml 文件配置方式

        基于注解方式

基于 XML 配置 bean

通过类型来获取 bean

通过 spring 的ioc 容器, 获取一个bean 对象

获取 bean 的方式:按类型

    public void getBeanByType() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");//,直接传入class对象/类型Monster bean = ioc.getBean(Monster.class);System.out.println("bean=" + bean);}

 Monster类

 注意

无参构造器一定要写,Spring反射创建对象时,需要使用 

public class Monster {private Integer monsterId;private String name;private String skill;//全参构造器public Monster(Integer monsterId, String name, String skill) {this.monsterId = monsterId;this.name = name;this.skill = skill;}//无参构造器一定要写,Spring反射创建对象时,需要使用public Monster() {}public Integer getMonsterId() {return monsterId;}public void setMonsterId(Integer monsterId) {this.monsterId = monsterId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSkill() {return skill;}public void setSkill(String skill) {this.skill = skill;}@Overridepublic String toString() {return "Monster{" +"monsterId=" + monsterId +", name='" + name + '\'' +", skill='" + skill + '\'' +'}';}
}

 xml配置

    <bean id="monster01" class="com.hspedu.spring.beans.Monster"><property name="monsterId" value="1"/><property name="name" value="牛魔王"/><property name="skill" value="牛魔王拳"/></bean>

细节说明

1. 按类型来获取 bean, 要求 ioc 容器中的同一个类的 bean 只能有一个,

否则会抛出异常 NoUniqueBeanDefinitionException 

2. 这种方式的应用场景:

比如 XxxAction/Servlet/Controller, 或 XxxService 在一个线程中只需要一个对象实例(单例)的情况

3. 这里在说明一下:

在容器配置文件(比如 beans.xml)中给属性赋值, 底层是通过setter 方法完成的, 这也是为什么我们需要提供 setter 方法的原因

通过构造器配置 bean 

    public void setBeanByConstructor() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");Monster monster03 = ioc.getBean("monster03", Monster.class);System.out.println("monster03=" + monster03);}

xml配置

1. constructor-arg标签可以指定使用构造器的参数
2. index表示构造器的第几个参数 从0开始计算的
3. 除了可以通过index 还可以通过 name / type 来指定参数方式
4. 解除大家的疑惑, 类的构造器,不能有完全相同类型和顺序的构造器,所以可以通过type来指定 

<!--配置Monster对象,并且指定构造器解读1. constructor-arg标签可以指定使用构造器的参数2. index表示构造器的第几个参数 从0开始计算的3. 除了可以通过index 还可以通过 name / type 来指定参数方式4. 解除大家的疑惑, 类的构造器,不能有完全相同类型和顺序的构造器,所以可以通过type来指定--><bean id="monster03" class="com.spring.bean.Monster"><constructor-arg value="200" index="0"/><constructor-arg value="白骨精" index="1"/><constructor-arg value="吸人血" index="2"/></bean><bean id="monster04" class="com.spring.bean.Monster"><constructor-arg value="200" name="monsterId"/><constructor-arg value="白骨精" name="name"/><constructor-arg value="吸人血" name="skill"/></bean><bean id="monster05" class="com.spring.bean.Monster"><constructor-arg value="300" type="java.lang.Integer"/><constructor-arg value="白骨精~" type="java.lang.String"/><constructor-arg value="吸人血~" type="java.lang.String"/></bean>

使用细节

1. 通过 index 属性来区分是第几个参数

2. 通过 type 属性来区是什么类型(按照顺序)

 

通过 p 名称空间配置 bean

 //通过p名称空间来设置属性@Testpublic void setBeanByP() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");Monster monster06 = ioc.getBean("monster06", Monster.class);System.out.println("monster06=" + monster06);}

 xml配置

<!--通过p名称空间来配置bean1. 将光标放在p , 输入alt+enter , 就会自动的添加xmlns2. 有时需要多来几次--><bean id="monster06" class="com.spring.bean.Monster"p:monsterId="500"p:name="红孩儿"p:skill="吐火"/>

 

引用/注入其它 bean 对象--ref

    //通过ref来设置bean属性@Testpublic void setBeanByRef() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");MemberServiceImpl memberService =ioc.getBean("memberService", MemberServiceImpl.class);memberService.add();}

 MemberDAOImpl

public class MemberDAOImpl {//构造器...public MemberDAOImpl() {//System.out.println("MemberDAOImpl 构造器被执行...");}//方法public void add() {//System.out.println("MemberDAOImpl add()方法被执行");}
}

 MemberServiceImpl 

public class MemberServiceImpl {private MemberDAOImpl memberDAO;public MemberServiceImpl() {//System.out.println("MemberServiceImpl() 构造器被执行");}public MemberDAOImpl getMemberDAO() {return memberDAO;}public void setMemberDAO(MemberDAOImpl memberDAO) {//System.out.println("setMemberDAO()...");this.memberDAO = memberDAO;}public void add() {System.out.println("MemberServiceImpl add() 被调用..");memberDAO.add();}
}

 xml配置

 <!--配置MemberServiceImpl对象1. ref="memberDAO"表示  MemberServiceImpl对象属性memberDAO引用的对象是id=memberDAO的对象2. 这里就体现出spring容器的依赖注入3. 注意再spring容器中, 他是作为一个整体来执行的, 即如果你引用到一个bean对象, 对你配置的顺序没有要求4. 建议还是按顺序,好处是阅读的时候,比较方便--><!--配置MemberDAOImpl对象--><bean class="com.spring.dao.MemberDAOImpl" id="memberDAO"/><bean class="com.spring.service.MemberServiceImpl" id="memberService"><property name="memberDAO" ref="memberDAO"/></bean>

 引用/注入内部 bean 对象--内部 bean 对象

1. 创建 MemberDAOImpl.java, 前面有了

2. 创建 MemberServiceImpl.java, 前面有 

    //通过内部bean设置属性@Testpublic void setBeanByPro() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");MemberServiceImpl memberService2 =ioc.getBean("memberService2", MemberServiceImpl.class);memberService2.add();}

只需要修改一下xml配置就好 

  xml配置

<!--配置MemberServiceImpl对象-使用内部bean--><bean class="com.hspedu.spring.service.MemberServiceImpl" id="memberService2"><!--自己配置一个内部bean--><property name="memberDAO"><bean class="com.spring.dao.MemberDAOImpl"/></property></bean>

 

引用/注入集合/数组类型

在 spring 的 ioc 容器, 看看如何给 bean

其中包括

list   map    set            数组        Properties

1. 创建 Monster.java, 前面有了

2. 创建Master.java

Master.java 

public class Master {private String name;//主人名private List<Monster> monsterList;private Map<String, Monster> monsterMap;private Set<Monster> monsterSet;//数组private String[] monsterName;//Java基础//这个Properties 是 Hashtable的子类 , 是key-value的形式//这里Properties  key和value 都是Stringprivate Properties pros;public String getName() {return name;}public void setName(String name) {this.name = name;}public List<Monster> getMonsterList() {return monsterList;}public void setMonsterList(List<Monster> monsterList) {this.monsterList = monsterList;}public Map<String, Monster> getMonsterMap() {return monsterMap;}public void setMonsterMap(Map<String, Monster> monsterMap) {this.monsterMap = monsterMap;}public Set<Monster> getMonsterSet() {return monsterSet;}public void setMonsterSet(Set<Monster> monsterSet) {this.monsterSet = monsterSet;}public String[] getMonsterName() {return monsterName;}public void setMonsterName(String[] monsterName) {this.monsterName = monsterName;}public Properties getPros() {return pros;}public void setPros(Properties pros) {this.pros = pros;}@Overridepublic String toString() {return "Master{" +"name='" + name + '\'' +", monsterList=" + monsterList +", monsterMap=" + monsterMap +", monsterSet=" + monsterSet +", monsterName=" + Arrays.toString(monsterName) +", pros=" + pros +'}';}
}

 配置 beans.xml

给list属性赋值
给map属性赋值
给set属性赋值


给数组属性赋值
        说一句: array标签中使用 value 还是 bean , ref .. 要根据你的业务决定


给Properties属性赋值 结构k(String)-v(String)

    <!--配置Master对象体会 spring 容器配置特点 依赖注入-非常灵活--><bean class="com.spring.bean.Master" id="master01"><property name="name" value="太上老君"/><!--给list属性赋值--><property name="monsterList"><list><!--引用的方法--><ref bean="monster01"/><ref bean="monster02"/><!--内部bean--><bean class="com.spring.bean.Monster"><property name="name" value="老鼠精"/><property name="monsterId" value="100"/><property name="skill" value="吃粮食"/></bean></list></property><!--给map属性赋值--><property name="monsterMap"><map><entry><key><value>monster03</value></key><!--这里使用的外部bean,引入--><ref bean="monster03"/></entry><entry><key><value>monster04</value></key><ref bean="monster04"/></entry></map></property><!--给set属性赋值--><property name="monsterSet"><set><ref bean="monster05"/><ref bean="monster06"/><bean class="com.spring.bean.Monster"><property name="name" value="金角大王"/><property name="skill" value="吐水"/><property name="monsterId" value="666"/></bean></set></property><!--给数组属性赋值说一句: array标签中使用 value 还是 bean , ref .. 要根据你的业务决定--><property name="monsterName"><array><value>小妖怪</value><value>大妖怪</value><value>老妖怪</value></array></property><!--给Properties属性赋值 结构k(String)-v(String)--><property name="pros"><props><prop key="username">root</prop><prop key="password">123456</prop><prop key="ip">127.0.0.1</prop></props></property></bean>

setCollectionByPro 

  • 获取 list 集合
  • 获取 map 集合
  • 获取 set
  • 获取数组
  • 获取 properties 集合
    public void setCollectionByPro() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");Master master01 = ioc.getBean("master01", Master.class);//获取 list 集合System.out.println("======list=======");List<Monster> monster_list = master01.getMonsterList();for (Monster monster : monster_list) {System.out.println(monster);}//获取 map 集合System.out.println("======map=======");Map<String, Monster> monster_map = master01.getMonsterMap();Set<Map.Entry<String, Monster>> entrySet = monster_map.entrySet();for (Map.Entry<String, Monster> entry : entrySet) {System.out.println(entry);}//获取 setSystem.out.println("======set=======");Set<Monster> monsterSet = master01.getMonsterSet();for (Monster monster : monsterSet) {System.out.println(monster);}//获取数组System.out.println("======数组=======");String[] monsterName = master01.getMonsterName();for (String s : monsterName) {System.out.println("妖怪名= " + s);}//获取 properties 集合System.out.println("======properties=======");Properties pros = master01.getPros();String property1 = pros.getProperty("k1");String property2 = pros.getProperty("k2");String property3 = pros.getProperty("k3");System.out.println(property1 + "\t" + property2 + "\t" + property3);}
}

通过 util 名称空间创建 list

spring 的 ioc 容器, 通过 util 名称空间来创建 list 集合,可以当做创建 bean 对象的工具来 

 //使用util:list名称空间给属性赋值@Testpublic void setBeanByUtilList() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");BookStore bookStore = ioc.getBean("bookStore", BookStore.class);System.out.println("bookStore=" + bookStore);}

创建BookStore 类

无参构造器,如果你没有其它的构造器,该无参构造器可以不写
但是如果你有其它的构造器,则必须显式的定义一下无参构造器 

public class BookStore {//书private List<String> bookList;//无参构造器,如果你没有其它的构造器,该无参构造器可以不写//但是如果你有其它的构造器,则必须显式的定义一下无参构造器public BookStore() {}public List<String> getBookList() {return bookList;}public void setBookList(List<String> bookList) {this.bookList = bookList;}@Overridepublic String toString() {return "BookStore{" +"bookList=" + bookList +'}';}
}

修改 beans.xml , 增加配置

如果没有自动导入则复制这二行  到上面

xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"

 <!--定义一个util:list 并且指定id 可以达到数据复用说明: 在使用util:list 名称空间时候,需要引入相应的标签, 一般来说通过alt+enter会自动加入, 如果没有就手动添加一下即可.--><util:list id="myBookList"><value>三国演义</value><value>红楼梦</value><value>西游记</value><value>水浒传</value></util:list><!--配置BookStore对象--><bean class="com.spring.bean.BookStore" id="bookStore"><property name="bookList" ref="myBookList"/></bean>

级联属性赋值

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

//给属性进行级联赋值@Testpublic void setBeanByRelation() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");Emp emp = ioc.getBean("emp", Emp.class);System.out.println("emp=" + emp);}

 

创建Dept.java

public class Dept {private String name;public Dept() {}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Dept{" +"name='" + name + '\'' +'}';}
}

创建Emp.java

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;}@Overridepublic String toString() {return "Emp{" +"name='" + name + '\'' +", dept=" + dept +'}';}
}

修改 beans.xml

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

 

通过静态工厂获取对象

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

重新在获取一个bean因为他们所指定的工厂是静态的只会执行一次 所以他们是同一个对象 

    //通过静态工厂获取bean//Java基础-静态和非静态@Testpublic void getBeanByStaticFactory() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");Monster my_monster01 = ioc.getBean("my_monster01", Monster.class);Monster my_monster04 = ioc.getBean("my_monster04", Monster.class);System.out.println("my_monster01=" + my_monster01);System.out.println(my_monster01 == my_monster04);//true}

MyStaticFactory类

public class MyStaticFactory {private static Map<String, Monster> monsterMap;//使用 static代码块 进行初始化//在java基础的时候,讲过的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. 通过静态工厂获取/配置bean2. class 是静态工厂类的全路径3. factory-method 表示是指定静态工厂类的哪个方法返回对象4. constructor-arg value="monster02" value是指定要返回静态工厂的哪个对象--><bean id="my_monster01"class="com.spring.factory.MyStaticFactory"factory-method="getMonster"><constructor-arg value="monster02"/></bean><bean id="my_monster04"class="com.spring.factory.MyStaticFactory"factory-method="getMonster"><constructor-arg value="monster02"/></bean>

 

通过实例工厂获取对象

在 spring 的 ioc 容器, 可以通过实例工厂获对象

重新在获取一个bean因为他们所指定的工厂是非静态的调用一次执行一次所以他们不是同一个对象  

    //通过实例工厂获取bean@Testpublic void getBeanByInstanceFactory() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");Monster my_monster02 = ioc.getBean("my_monster02", Monster.class);Monster my_monster03 = ioc.getBean("my_monster03", Monster.class);System.out.println("my_monster02=" + my_monster02);System.out.println("my_monster03=" + my_monster03);System.out.println(my_monster02 == my_monster03);//false}

MyInstanceFactory 类 

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

1. factory-bean 指定使用哪个实例工厂对象返回bean
2. factory-method 指定使用实例工厂对象的哪个方法返回bean
3. constructor-arg value="monster03" 指定获取到实例工厂中的哪个monster 

<!--配置2个实例工厂对象--><bean class="com.spring.factory.MyInstanceFactory" id="myInstanceFactory"/><bean class="com.spring.factory.MyInstanceFactory" id="myInstanceFactory2"/><!--配置monster对象, 通过实例工厂解读1. factory-bean 指定使用哪个实例工厂对象返回bean2. factory-method 指定使用实例工厂对象的哪个方法返回bean3. constructor-arg value="monster03" 指定获取到实例工厂中的哪个monster--><bean id="my_monster02" factory-bean="myInstanceFactory" factory-method="getMonster"><constructor-arg value="monster03"/></bean><bean id="my_monster03" factory-bean="myInstanceFactory2" factory-method="getMonster"><constructor-arg value="monster03"/></bean>

 

通过 FactoryBean 获取对象

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

    //通过FactoryBean获取bean@Testpublic void getBeanByFactoryBean() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");Monster my_monster05 = ioc.getBean("my_monster05", Monster.class);System.out.println("my_monster05=" + my_monster05);}

 

创建 MyFactoryBean  

public class MyFactoryBean implements FactoryBean<Monster> {//这个就是你配置时候,指定要获取的对象对应keyprivate String key;private Map<String, Monster> monster_map;{   //代码块,完成初始化monster_map = new HashMap<>();monster_map.put("monster03", new Monster(300, "牛魔王~", "芭蕉扇~"));monster_map.put("monster04", new Monster(400, "狐狸精~", "美人计~"));}public void setKey(String key) {this.key = key;}@Overridepublic Monster getObject() throws Exception {return monster_map.get(key);}@Overridepublic Class<?> getObjectType() {//得到类型return Monster.class;}@Overridepublic boolean isSingleton() {//这里指定是否返是单例return false;}
}

配置beans.xml

  <!--配置monster对象,通过FactoryBean获取解读1. class 指定使用的FactoryBean2. key表示就是 MyFactoryBean 属性key3. value就是你要获取的对象对应key--><bean id="my_monster05" class="com.spring.factory.MyFactoryBean"><property name="key" value="monster04"/></bean>

bean 配置信息重用(继承)

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

 //配置Bean通过继承@Testpublic void getBeanByExtends() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");Monster monster11 = ioc.getBean("monster11", Monster.class);System.out.println("monster11=" + monster11);Monster monster13 = ioc.getBean("monster13", Monster.class);System.out.println("monster13=" + monster13);}

 配置beans.xml

1. 配置Monster对象
2.但是这个对象的属性值和 id="monster10"对象属性一样
3.parent="monster10" 指定当前这个配置的对象的属性值从 id=monster10的对象来

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

bean 创建顺序

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

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

1. 在默认情况下, bean创建的顺序是按照配置顺序来的
2. 但是如果我们增加了 depends-on="department01" 这时就会先创建id= department01对象

配置Monster对象

1. 如果bean指定了 abstract="true", 表示该bean对象, 是用于被继承
 2. 本身这个bean就不能被获取/实例化

 配置beans.xml 

<!--测试bean对象的创建顺序1. 在默认情况下, bean创建的顺序是按照配置顺序来的2. 但是如果我们增加了 depends-on="department01" 这时就会先创建id= department01对象--><bean id="student01" class="com.hspedu.spring.bean.Student" depends-on="department01"/><bean id="department01" class="com.hspedu.spring.bean.Department"/><!--配置Monster对象1. 如果bean指定了 abstract="true", 表示该bean对象, 是用于被继承2. 本身这个bean就不能被获取/实例化--><bean id="monster12" class="com.hspedu.spring.bean.Monster" abstract="true"><property name="monsterId" value="100"/><property name="name" value="蜈蚣精~"/><property name="skill" value="蜇人~"/></bean><bean id="monster13" class="com.hspedu.spring.bean.Monster" parent="monster12"/>

bean 对象的单例和多例

● 说明

 

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

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

创建car.java 

public class Car {private Integer id;private String name;private Integer price;public Car(Integer id, String name, Integer price) {this.id = id;this.name = name;this.price = price;}public Car() {}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;}public Integer getPrice() {return price;}public void setPrice(Integer price) {this.price = price;}@Overridepublic String toString() {return "Car{" +"id=" + id +", name='" + name + '\'' +", price=" + price +'}';}
}

 配置beans.xml

1. 在默认情况下 scope属性是 singleton

2. 在ioc容器中, 只要有一个这个bean对象

3. 当程序员执行getBean时, 返回的的是同一个对象

4. 如果我们希望每次getBean返回一个新的Bean对象,则可以scope="prototype"

5. 如果bean的配置是 scope="singleton" lazy-init="true" 这时,ioc容器就不会提前创建该对象, 而是当执行getBean方法的时候,才会创建对象 

 <!--配置Cat对象1. 在默认情况下 scope属性是 singleton2. 在ioc容器中, 只要有一个这个bean对象3. 当程序员执行getBean时, 返回的的是同一个对象4. 如果我们希望每次getBean返回一个新的Bean对象,则可以scope="prototype"5. 如果bean的配置是 scope="singleton" lazy-init="true" 这时,ioc容器就不会提前创建该对象, 而是当执行getBean方法的时候,才会创建对象--><bean id="cat" class="com.spring.bean.Cat" scope="prototype" lazy-init="false"><property name="id" value="100"/><property name="name" value="小花猫"/></bean>
 @Testpublic void testBeanScope() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");Cat cat = ioc.getBean("cat", Cat.class);Cat cat2 = ioc.getBean("cat", Cat.class);Cat cat3 = ioc.getBean("cat", Cat.class);System.out.println("cat=" + cat);System.out.println("cat2=" + cat2);System.out.println("cat3=" + cat3);}

 

使用细节

1. 默认是单例 scope=singleton,

在启动容器时, 默认就会创建 , 并放入到 singletonObjects 集合

2. 当 <bean scope="prototype" >

设置为多实例机制后, 该 bean 是在 getBean()时才创建

3. 如果是单例 scope=singleton,

同时希望在 getBean 时才创建 , 可以指定懒加载lazy init="true" (注意默认是 false)

4. 通常情况下,

lazy-init 就使用默认值 false , 在开发看来, 用空间换时间是值得的, 除非有特殊的要求. 

5. 如果 scope="prototype"

这时你的 lazy-init 属性的值不管是 ture, 还是 false 都是在getBean 时候,才创建对象

 

 bean 的生命周期

● 说明:

bean 对象创建是由 JVM 完成的,然后执行如下方法

1. 执行构造器
2. 执行 set 相关方法
3. 调用 bean 的初始化的方法
4. 使用 bean
5. 当容器关闭时候,调用 bean 的销毁方法

1. 这里java基础
2. ioc的编译类型 ApplicationContext , 运行类型 ClassPathXmlApplicationContext
3. 因为ClassPathXmlApplicationContext 实现了 ConfigurableApplicationContext
4. ClassPathXmlApplicationContext 是有close
5. 将ioc 转成ClassPathXmlApplicationContext,再调用close
ioc.close();关闭ioc容器. 

    public void testBeanLife() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans.xml");House house = ioc.getBean("house", House.class);System.out.println("使用house=" + house);//关闭容器//1. 这里又要考察大家的java基础//2. ioc的编译类型 ApplicationContext , 运行类型 ClassPathXmlApplicationContext//3. 因为ClassPathXmlApplicationContext 实现了 ConfigurableApplicationContext//4. ClassPathXmlApplicationContext 是有close//5. 将ioc 转成ClassPathXmlApplicationContext,再调用close//ioc.close();//关闭ioc容器.((ConfigurableApplicationContext) ioc).close();}

         

创建House.java

public class House {private String name;public House() {System.out.println("House() 构造器...");}public String getName() {return name;}public void setName(String name) {System.out.println("House setName()=" + name);this.name = name;}//1. 这个方法是程序员来编写的.//2. 根据自己的业务逻辑来写.public void init() {System.out.println("House init()..");}//1. 这个方法是程序员来编写的.//2. 根据自己的业务逻辑来写.//3. 名字也不是固定的public void destroy() {System.out.println("House destroy()..");}@Overridepublic String toString() {return "House{" +"name='" + name + '\'' +'}';}
}

 配置beans.xml 

1. init-method="init" 指定bean的初始化方法 , 在setter方法后执行
2. init方法执行的时机,有spring容器来控制
3. destroy-method="destroy" 指定bean的销毁方法, 在容器关闭的时候执行
4. destroy方法执行的时机,有spring容器来控制 

    <!--配置House对象,演示整个Bean的生命周期解读1. init-method="init" 指定bean的初始化方法 , 在setter方法后执行2. init方法执行的时机,有spring容器来控制3. destroy-method="destroy" 指定bean的销毁方法, 在容器关闭的时候执行4. destroy方法执行的时机,有spring容器来控制--><bean class="com.spring.bean.House" id="house"init-method="init"destroy-method="destroy"><property name="name" value="北京豪宅"/></bean>

 使用细节

1. 初始化 init 方法和 destory 方法, 是程序员来指定
2. 销毁方法就是当关闭容器时,才会被调用

 

配置 bean 的后置处理器

 说明

1. 在 spring 的 ioc 容器,可以配置 bean 的后置处理器
2. 该处理器/对象会在 bean 初始化方法调用前和初始化方法调用后被调用
3. 程序员可以在后置处理器中编写自己的代码

@Testpublic void testBeanPostProcessor() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans02.xml");House house = ioc.getBean("house", House.class);System.out.println("使用house=" + house);House house02 = ioc.getBean("house02", House.class);System.out.println("使用house02=" + house02);((ConfigurableApplicationContext)ioc).close();}

 

创建 House.java 前面有 

创建后置处理器MyBeanPostProcessor.java

什么时候被调用: 在Bean的init方法前被调用
@param bean 传入的在IOC容器中创建/配置Bean
@param beanName 传入的在IOC容器中创建/配置Bean的id
@return Object 程序员对传入的bean 进行修改/处理【如果有需要的话】 ,返回
@throws BeansException 

什么时候被调用: 在Bean的init方法后被调用
@param bean  传入的在IOC容器中创建/配置Bean
@param beanName 传入的在IOC容器中创建/配置Bean的id
@return 程序员对传入的bean 进行修改/处理【如果有需要的话】 ,返回
@throws BeansException

public class MyBeanPostProcessor implements BeanPostProcessor {/*** 什么时候被调用: 在Bean的init方法前被调用* @param bean 传入的在IOC容器中创建/配置Bean* @param beanName 传入的在IOC容器中创建/配置Bean的id* @return Object 程序员对传入的bean 进行修改/处理【如果有需要的话】 ,返回* @throws BeansException*/@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization().. bean="+ bean + " beanName=" + beanName);//初步体验案例: 如果类型是House的统一改成 上海豪宅//对多个对象进行处理/编程==>切面编程if(bean instanceof House) {((House)bean).setName("上海豪宅~");}return null;}/*** 什么时候被调用: 在Bean的init方法后被调用* @param bean  传入的在IOC容器中创建/配置Bean* @param beanName 传入的在IOC容器中创建/配置Bean的id* @return 程序员对传入的bean 进行修改/处理【如果有需要的话】 ,返回* @throws BeansException*/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization().. bean="+ bean + " beanName=" + beanName);return bean;}
}

 配置beans.xml 

1. 当我们在   .xml 容器配置文件 配置了 MyBeanPostProcessor
2. 这时后置处理器对象,就会作用在该容器创建的Bean对象
3. 已经是针对所有对象编程->切面编程AOP 

 <!--配置House对象--><bean class="com.spring.bean.House" id="house"init-method="init"destroy-method="destroy"><property name="name" value="大豪宅"/></bean><bean class="com.spring.bean.House" id="house02"init-method="init"destroy-method="destroy"><property name="name" value="香港豪宅"/></bean><!--配置了一个Monster对象--><!--配置后置处理器对象1. 当我们在beans02.xml 容器配置文件 配置了 MyBeanPostProcessor2. 这时后置处理器对象,就会作用在该容器创建的Bean对象3. 已经是针对所有对象编程->切面编程AOP--><bean class="com.spring.bean.MyBeanPostProcessor" id="myBeanPostProcessor"/>

其它说明

1、怎么执行到这个方法?=> 使用 AOP(反射+动态代理+IO+容器+注解)

2、有什么用?=> 可以对 IOC 容器中所有的对象进行统一处理 ,比如 日志处理/权限的校验/安全的验证/事务管理. -      初步体验: 如果类型是 House 的统一改成 上海豪宅

3、针对容器的所有对象吗? 是的=>切面编程特点

 

通过属性文件给 bean 注入值 

src/ 创建 my.properties

name=\u9EC4\u888D\u602A

id=10

skill=\u72EE\u5B50\u543C 

  @Testpublic void setBeanByFile() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans03.xml");Monster monster1000 = ioc.getBean("monster1000", Monster.class);System.out.println("monster1000=" + monster1000);}

1. 先把这个文件修改成提示All Problem
2. 提示错误,将光标放在context 输入alt+enter 就会自动引入namespace
3. location="classpath:my.properties" 表示指定属性文件的位置
4. 提示,需要带上 classpath
5. 属性文件有中文,需要将其转为unicode编码-> 使用工具


<context:property-placeholder location="classpath:my.properties"/>
配置Monster对象

1.通过属性文件给monster对象的属性赋值
2. 这时我们的属性值通过${属性名}
3. 这里说的 属性名 就是 my.properties文件中的 k=v 的k

 配置beans.xml  

<!--指定属性文件1. 先把这个文件修改成提示All Problem2. 提示错误,将光标放在context 输入alt+enter 就会自动引入namespace3. location="classpath:my.properties" 表示指定属性文件的位置4. 提示,需要带上 classpath5. 属性文件有中文,需要将其转为unicode编码-> 使用工具--><context:property-placeholder location="classpath:my.properties"/><!--配置Monster对象1.通过属性文件给monster对象的属性赋值2. 这时我们的属性值通过${属性名}3. 这里说的 属性名 就是 my.properties文件中的 k=v 的k--><bean class="com.spring.bean.Monster" id="monster1000"><property name="monsterId" value="${monsterId}"/><property name="skill" value="${skill}"/><property name="name" value="${name}"/></bean>

基于 XML 的 bean 的自动装配

在 spring 的 ioc 容器,可以实现自动装配 bean

这里说的 Action 就是 Servlet->充当 Controller

OrderDao

public class OrderDao {
    //方法。。。
    public void saveOrder() {
        System.out.println("保存 一个订单...");
    }
}

OrderService

public class OrderService {//OrderDao属性private OrderDao orderDao;//getterpublic OrderDao getOrderDao() {return orderDao;}//setterpublic void setOrderDao(OrderDao orderDao) {this.orderDao = orderDao;}
}

OrderAction  

public class OrderAction {//属性OrderServiceprivate OrderService orderService;//getterpublic OrderService getOrderService() {return orderService;}//setterpublic void setOrderService(OrderService orderService) {this.orderService = orderService;}
}

  配置beans.xml 

1. autowire="byType" 表示 在创建 orderService时通过类型的方式 给对象属性 自动完成赋值/引用
2. 比如OrderService 对象有 private OrderDao orderDao
3. 就会在容器中去找有没有 OrderDao类型对象
4. 如果有,就会自动的装配, 老师提示如果是按照 byType 方式来装配, 这个容器中,不能有两个 的OrderDao类型对象
 5. 如果你的对象没有属性,  autowire就没有必要写
6. 其它类推..

7. 如果我们设置的是 autowire="byName" 表示通过名字完成自动装配
8. 比如下面的 autowire="byName" class="com.hspedu.spring.service.OrderService"
      1) 先看 OrderService 属性 private OrderDao orderDao
      2) 再根据这个属性的setXxx()方法的 xxx 来找对象id
      3) public void setOrderDao() 就会找id=orderDao对象来进行自动装配
      4) 如果没有就装配失败

    <!--配置OrderDao对象--><bean class="com.spring.dao.OrderDao" id="orderDao"/><!--配置OrderService对象1. autowire="byType" 表示 在创建 orderService时通过类型的方式 给对象属性 自动完成赋值/引用2. 比如OrderService 对象有 private OrderDao orderDao3. 就会在容器中去找有没有 OrderDao类型对象4. 如果有,就会自动的装配, 老师提示如果是按照 byType 方式来装配, 这个容器中,不能有两个的OrderDao类型对象5. 如果你的对象没有属性,  autowire就没有必要写6. 其它类推..7. 如果我们设置的是 autowire="byName" 表示通过名字完成自动装配8. 比如下面的 autowire="byName" class="com.spring.service.OrderService"1) 先看 OrderService 属性 private OrderDao orderDao2) 再根据这个属性的setXxx()方法的 xxx 来找对象id3) public void setOrderDao() 就会找id=orderDao对象来进行自动装配4) 如果没有就装配失败--><bean autowire="byName" class="com.spring.service.OrderService"id="orderService"/><!--配置OrderAction--><bean autowire="byName" class="com.spring.web.OrderAction" id="orderAction"/>

spring eel 表达式

1. Spring Expression Language,Spring 表达式语言,简称 SpEL。支持运行时查询并可以操作对象。
2. 和 EL 表达式一样,SpEL 根据 JavaBean 风格的 getXxx()、setXxx()方法定义的属性访问对象
3. SpEL 使用#{…}作为定界符,所有在大框号中的字符都将被认为是 SpEL 表达式。
4. 不是重点,如果看到有人这样使用,能看懂即可

 SpELBean.java

public class SpELBean {private String name;private Monster monster;private String monsterName;private String crySound; //叫声private String bookName;private Double result;public SpELBean() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public Monster getMonster() {return monster;}public void setMonster(Monster monster) {this.monster = monster;}public String getMonsterName() {return monsterName;}public void setMonsterName(String monsterName) {this.monsterName = monsterName;}public String getCrySound() {return crySound;}public void setCrySound(String crySound) {this.crySound = crySound;}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public Double getResult() {return result;}public void setResult(Double result) {this.result = result;}//cry 方法会返回字符串public String cry(String sound) {return "发出 " + sound + "叫声...";}//read 返回字符串public static String read(String bookName) {return "正在看 " + bookName;}@Overridepublic String toString() {return "SpELBean{" +"name='" + name + '\'' +", monster=" + monster +", monsterName='" + monsterName + '\'' +", crySound='" + crySound + '\'' +", bookName='" + bookName + '\'' +", result=" + result +'}';}
}

  配置beans.xml  

通过spel给bean的属性赋值 

<!-- spring el 表达式使用1. 通过spel给bean的属性赋值--><bean id="spELBean" class="com.hspedu.spring.bean.SpELBean"><!-- sp el 给字面量 --><property name="name" value="#{'大家好'}"/><!-- sp el 引用其它bean --><property name="monster" value="#{monster01}"/><!-- sp el 引用其它bean的属性值 --><property name="monsterName" value="#{monster01.name}"/><!-- sp el 调用普通方法(返回值)  赋值 --><property name="crySound" value="#{spELBean.cry('喵喵的..')}"/><!-- sp el 调用静态方法(返回值) 赋值 --><property name="bookName" value="#{T(com.spring.bean.SpELBean).read('天龙八部')}"/><!-- sp el 通过运算赋值 --><property name="result" value="#{89*1.2}"/></bean>

测试

 //通过spring el 对属性赋值@Testpublic void setBeanBySpel() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans04.xml");SpELBean spELBean = ioc.getBean("spELBean", SpELBean.class);System.out.println("spELBean=" + spELBean);}

文章来源:https://blog.csdn.net/apple_67445472/article/details/130451107
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ppmy.cn/news/55530.html

相关文章

函数(详解)——C语言

Hello&#xff0c;友友们前段时间忙拖更了这么久&#xff0c;趁着五一假期好好卷上一波哈哈哈。好的&#xff0c;我们本期主要对C语言中的函数进行讲解。 1.什么是函数 在数学中也常常用到函数&#xff0c;但你对C语言中的函数有了解吗&#xff1f; 在C语言中函数是一段可重…

【计算机网络详解】——物理层(学习笔记)

&#x1f4d6; 前言&#xff1a;今天我们将一起探索电脑网络中最基础的一层&#xff0c;物理层。从摩斯电码到光纤传输的高速互联网时代&#xff0c;物理层在不断发展和创新。让我们一起深入到网络通讯的本质&#xff0c;探究物理层与我们的日常联系密不可分的原因。 目录 &…

java学习需要掌握的几个细节点,分享一下我找工作的技巧

现在想跟大家聊聊最近的一些想法和状态。最近学习的时间比较少&#xff0c;几乎没怎么学。没有像以前学的那么卷了&#xff0c;可以说。主要是心态受到了一些影响&#xff0c;比如网上看到说招个岗位几百比1这种。 另一个是自己的感受&#xff0c;现在投简历的回应包括能不能投…

Java中的String、StringBuffer和StringBuilder

文章目录 Java中的String、StringBuffer和StringBuilderString 类型特点操作 StringBuffer 类型特点操作 StringBuilder 类型特点操作 总结代码实践注意事项 Java中的String、StringBuffer和StringBuilder 在 Java 中&#xff0c;字符串是最常用的数据类型之一。 Java 中有三种…

新品首发丨计讯物联5G水利遥测终端机TY511-B3,推动5G+智慧水利再进化

当前&#xff0c;水利在全面感知、全面互联、智慧应用等方面较其他行业存在明显差距。基于物联网行业通信技术的不断突破和水利行业对高速移动通信的强烈需求&#xff0c;5G移动通信以高速率、大带宽、低时延、广连接等特点让水利数据快速高效地传输成为可能&#xff0c;逐渐成…

ecs思考

VPC网络诊断&#xff0c;从router看起&#xff0c;连接公有子网路有一个默认&#xff0c;再新增一条指向igw路由&#xff1b;连接私有子网路由有一个默认&#xff0c;再新增一条指向NAT网关的路由&#xff0c;其中NAT网关一定要在公有子网中&#xff0c;否则&#xff0c;私有子…

Java 怎样实现代理模式,有什么优缺点

一、介绍 代理模式是一种常见的设计模式&#xff0c;它可以为其他对象提供一种代理以控制对这个对象的访问。代理对象具有与被代理对象相同的接口&#xff0c;客户端无需知道代理对象和被代理对象的区别。代理模式可以应用于各种不同的场景&#xff0c;例如远程代理、虚拟代理…

链表的添加修改删除操作

public class HeroNodeDemo {public static void main(String[] args) {HeroNode hero1 new HeroNode(1, "松江");HeroNode hero2 new HeroNode(2, "武松");HeroNode hero3 new HeroNode(3, "及时雨");HeroNode hero4 new HeroNode(4, "…