南飓风 发表于 4 天前

Spring3-IoC1-IoC容器、基于xml管理bean

目次
IoC容器
概述
依赖注入
IoC容器在Spring中的实现
基于xml管理bean
获取bean
依赖注入
setter注入
构造器注入
特殊值处理
字面量赋值
null值
xml实体
CDATA节
特殊范例属性注入
对象范例属性注入
方式一:引用外部bean
方式二:内部bean
方式三:级联属性赋值
数组范例属性注入
集合范例属性注入
list、set集合范例
map集合范例
引用集合范例 
p命名空间
引入外下属性文件
bean的作用域
bean的生命周期
FactoryBean
基于xml自动装配
IoC容器

概述

IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种计划思想,是一个告急的面向对象编程法则,可以或许指导我们怎样计划出松耦合、更优良的步伐
Spring 通过 IoC 容器来管理全部 Java 对象的实例化和初始化,控制对象与对象之间的依赖关系。我们将由 IoC 容器管理的 Java 对象称为 Spring Bean,它与使用关键字 new 创建的 Java 对象没有任何区别
控制反转是一种思想
控制反转是为了低落步伐耦合度,提高步伐扩展力
控制反转,反转的是什么?


[*]将对象的创建权利交出去,交给第三方容器负责
[*]将对象和对象之间关系的维护权交出去,交给第三方容器负责
控制反转这种思想怎样实现呢?


[*]DI(Dependency Injection):依赖注入  
依赖注入

DI(Dependency Injection):依赖注入,依赖注入实现了控制反转的思想
依赖注入:Spring创建对象的过程中,将对象依赖属性通过配置进行注入
依赖注入常见的实现方式包括两种:


[*]set注入
[*]构造注入
Bean管理:Bean对象的创建以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)
IoC容器在Spring中的实现

Spring 的 IoC 容器就是 IoC思想的一个落地的产物实现。IoC容器中管理的组件也叫做 bean。在创建 bean 之前,起首需要创建IoC 容器。Spring 提供了IoC 容器的两种实现方式:
①BeanFactory
这是 IoC 容器的根本实现,是 Spring 内部使用的接口。面向 Spring 本身,不提供给开发人员使用
②ApplicationContext
BeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎全部场合都使用ApplicationContext,而不是底层的 BeanFactory
ApplicationContext的主要实现类:
范例名简介ClassPathXmlApplicationContext通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象FileSystemXmlApplicationContext通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象ConfigurableApplicationContextApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、关闭和刷新上下文的本领WebApplicationContext专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中 基于xml管理bean

依赖放入父模块
创建新模块spring-ioc-xml
package com.qcby.spring;

public class User {
    private String name;
    private Integer age;

    public void run(){
      System.out.println("run...");
    }
}
获取bean

①方式一:根据id获取
由于 id 属性指定了 bean 的唯一标识,以是根据 bean 标签的 id 属性可以精确获取到一个组件对象(入门案例)
bean.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--user对象创建-->
    <bean id="user" class="com.qcby.spring.User"></bean>
</beans> 测试类: 
package com.qcby.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

      //根据id获取bean
      User user = (User) context.getBean("user");
      System.out.println("根据id获取bean:"+user);
    }
}
https://i-blog.csdnimg.cn/direct/199f4efb067745f586d55f4b87db494b.png
②方式二:根据范例获取
package com.qcby.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

      //根据id获取bean
//      User user = (User) context.getBean("user");
//      System.out.println("根据id获取bean:"+user);

      //根据类型获取bean
      User user = context.getBean(User.class);
      System.out.println("根据类型获取bean"+user);
    }
}
https://i-blog.csdnimg.cn/direct/39abd2b143144df8bad3056bcb24196e.png
当根据范例获取bean时,要求IOC容器中指定范例的bean有且只能有一个 
若配置多个,会抛出异常:org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type
③方式三:根据id和范例
package com.qcby.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

      //根据id获取bean
//      User user = (User) context.getBean("user");
//      System.out.println("根据id获取bean:"+user);

      //根据类型获取bean
//      User user = context.getBean(User.class);
//      System.out.println("根据类型获取bean"+user);

      //根据id和类型获取bean
      User user = context.getBean("user", User.class);
      System.out.println("根据id和类型获取bean:"+user);

    }
}
https://i-blog.csdnimg.cn/direct/4d632098650c45c5b32946fc4586c7dd.png
扩展:
如果组件类实现了接口,根据接口范例可以获取 bean 吗?


[*]可以,前提是bean唯一
package com.qcby.spring;

public interface UserDao {
    public void run();
}
package com.qcby.spring;

public class UserDaoImpl implements UserDao{
    @Override
    public void run() {
      System.out.println("run...");
    }
}
<!--一个接口获取类过程-->
<bean id="userDaoImpl" class="com.qcby.spring.bean.UserDaoImpl.UserDaoImpl"></bean> package com.qcby.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUserDao {
    public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
      //根据类型获取接口对应bean
      UserDao userDao = context.getBean(UserDao.class);
      System.out.println(userDao);
      userDao.run();
    }
}
https://i-blog.csdnimg.cn/direct/8809867a06924724b8790a5acedb077e.png


如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口范例可以获取 bean 吗?


[*]不可,因为bean不唯一
依赖注入

setter注入

第一步:创建类,天生属性set方法
第二步:在spring配置文件配置
package com.qcby.spring.di;

public class Book {
    private String bname;
    private String author;

    //无参构造
    public Book() {
    }

    //有参构造
    public Book(String bname, String author) {
      this.bname = bname;
      this.author = author;
    }

    //生成get和set方法
    public void setBname(String bname) {
      this.bname = bname;
    }

    public void setAuthor(String author) {
      this.author = author;
    }

    public String getBname() {
      return bname;
    }

    public String getAuthor() {
      return author;
    }

    @Override
    public String toString() {
      return "Book{" +
                "bname='" + bname + '\'' +
                ", author='" + author + '\'' +
                '}';
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

    <!--set方法注入-->
    <!-- property标签:通过组件类的setXxx()方法给组件对象设置属性 -->
    <!-- name属性:指定属性名(这个属性名是getXxx()、setXxx()方法定义的,和成员变量无关) -->
    <!-- value属性:指定属性值 -->
    <bean id="book" class="com.qcby.spring.di.Book">
      <property name="bname" value="前端开发"></property>
      <property name="author" value="张三"></property>
    </bean>
</beans> package com.qcby.spring;


import com.qcby.spring.di.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBook {
    @Test
    public void testSetter(){
      ApplicationContext context = new ClassPathXmlApplicationContext("bean_di.xml");
      Book book = context.getBean("book", Book.class);
      System.out.println(book);
    }

}
https://i-blog.csdnimg.cn/direct/13ec0c29e2654cd681ad0064dd3f148d.png
构造器注入

第一步:创建类,定义属性,天生有参构造方法
第二步:在spring配置文件配置
    <!--构造器注入-->
    <bean id="bookCon" class="com.qcby.spring.di.Book">
      <constructor-arg name="bname" value="java开发"></constructor-arg>
      <constructor-arg name="author" value="李四"></constructor-arg>
    </bean> 留意:
constructor-arg标签还有两个属性可以进一步描述构造器参数:


[*]index属性:指定参数所在位置的索引(从0开始)
[*]name属性:指定参数名
    @Test
    public void testCon(){
      ApplicationContext context = new ClassPathXmlApplicationContext("bean_di.xml");
      Book book = context.getBean("bookCon", Book.class);
      System.out.println(book);
    } https://i-blog.csdnimg.cn/direct/2096c56c3e4445009ce91fed465da69a.png
特殊值处理

字面量赋值

什么是字面量?
int a = 10;
声明一个变量a,初始化为10,此时a不代表字母a,而是作为一个变量的名字。当引用a的时候,实际上拿到的值是10。
而如果a是带引号的:'a',那么它如今不是一个变量,它就是代表a这个字母本身,这就是字面量。以是字面量没有引申含义,就是我们看到的这个数据本身
<!-- 使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量 -->
<property name="name" value="张三"/> null值

<property name="name">
    <null />
</property> 留意:以下写法为name所赋的值是字符串null
<property name="name" value="null"></property> xml实体

<!-- 小于号在XML文档中用来定义标签的开始,不能随便使用 -->
<!-- 解决方案一:使用XML实体来代替 -->
<property name="expression" value="a &lt; b"/> CDATA节

<property name="expression">
    <!-- 解决方案二:使用CDATA节 -->
    <!-- CDATA中的C代表Character,是文本、字符的含义,CDATA就表示纯文本数据 -->
    <!-- XML解析器看到CDATA节就知道这里是纯文本,就不会当作XML标签或属性来解析 -->
    <!-- 所以CDATA节中写什么符号都随意 -->
    <value><!]></value>
</property> 特殊范例属性注入

对象范例属性注入

https://i-blog.csdnimg.cn/direct/e774e5ef15de488ab874adeed2849582.png
package com.qcby.spring.ditest;

//部门类
public class Dept {
    private String dname;

    public void info(){
      System.out.println("部门名称:"+dname);
    }

    public void setDname(String dname) {
      this.dname = dname;
    }

    public String getDname() {
      return dname;
    }
}
package com.qcby.spring.ditest;

//员工类
public class Emp {
    //对象类型属性:员工属于某个部门
    private Dept dept;

    private String ename;
    private Integer age;

    public void work(){
      System.out.println(ename+"emp work..."+age);
      dept.info();
    }

    public Dept getDept() {
      return dept;
    }

    public void setDept(Dept dept) {
      this.dept = dept;
    }

    public String getEname() {
      return ename;
    }

    public void setEname(String ename) {
      this.ename = ename;
    }

    public Integer getAge() {
      return age;
    }

    public void setAge(Integer age) {
      this.age = age;
    }
}
方式一:引用外部bean

使用ref属性
    <!--方式一:引入外部bean
      1.创建两个类对象:dept emp
      2.在emp的bean标签里,使用property引入dept的bean
    -->
    <bean id="dept" class="com.qcby.spring.ditest.Dept">
      <property name="dname" value="安保部"></property>
    </bean>

    <bean id="emp" class="com.qcby.spring.ditest.Emp">
      <!--普通属性注入-->
      <property name="ename" value="lucy"></property>
      <property name="age" value="50"></property>
      <!--对象属性注入
      ref属性:引用IOC容器中某个bean的id,将所对应的bean为属性赋值-->
      <property name="dept" ref="dept"></property>
    </bean> https://i-blog.csdnimg.cn/direct/a7147e60cd444735828f0180d23ef907.png
方式二:内部bean

    <!--方式二:内部bean-->
    <!-- 在一个bean中再声明一个bean就是内部bean -->
    <!-- 内部bean只能用于给属性赋值,不能在外部通过IOC容器获取,因此可以省略id属性 -->
    <bean id="emp2" class="com.qcby.spring.ditest.Emp">
      <!--普通属性注入-->
      <property name="ename" value="mary"></property>
      <property name="age" value="20"></property>
      <!--对象属性注入-->
      <property name="dept">
            <bean id="dept2" class="com.qcby.spring.ditest.Dept">
                <property name="dname" value="财务部"></property>
            </bean>
      </property>
    </bean> https://i-blog.csdnimg.cn/direct/0bea45bd83bd4407ad3495f36fdde8f8.png
方式三:级联属性赋值

    <!--方式三:级联赋值-->
    <bean id="dept3" class="com.qcby.spring.ditest.Dept">
      <property name="dname" value="研发部"></property>
    </bean>
    <bean id="emp3" class="com.qcby.spring.ditest.Emp">
      <!--普通属性注入-->
      <property name="ename" value="tom"></property>
      <property name="age" value="30"></property>
      <!--对象属性注入-->
      <property name="dept" ref="dept3"></property>
      <property name="dept.dname" value="测试部"></property>
    </bean> https://i-blog.csdnimg.cn/direct/65770bc6d2744efcbf95398d8787dbb3.png
数组范例属性注入

员工类:
    //爱好
    private String[] loves;

    public String[] getLoves() {
      return loves;
    }

    public void setLoves(String[] loves) {
      this.loves = loves;
    }

    public void work(){
      System.out.println(ename+"emp work..."+age);
      dept.info();
      System.out.println(Arrays.toString(loves));
    }       <!--数组类型属性-->
      <property name="loves">
            <array>
                <value>吃饭</value>
                <value>睡觉</value>
                <value>看电影</value>
            </array>
      </property> 完整的配置文件:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean id="dept" class="com.qcby.spring.ditest.Dept">      <property name="dname" value="技术部"></property>    </bean>    <bean id="emp" class="com.qcby.spring.ditest.Emp">      <!--普通属性-->      <property name="ename" value="lucy"></property>      <property name="age" value="20"></property>      <!--对象范例属性-->      <property name="dept" ref="dept"></property>      <!--数组类型属性-->
      <property name="loves">
            <array>
                <value>吃饭</value>
                <value>睡觉</value>
                <value>看电影</value>
            </array>
      </property>   </bean></beans> https://i-blog.csdnimg.cn/direct/32f226ef0900403db567fcc9f0c949d1.png
集合范例属性注入

list、set集合范例

Dept类:

    private List<Emp> empList;
   

    public void info(){
      System.out.println("部门名称:"+dname);
      for (Emp emp : empList) {
            System.out.println(emp.getEname());
      }
    }

    public List<Emp> getEmpList() {
      return empList;
    }

    public void setEmpList(List<Emp> empList) {
      this.empList = empList;
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="empone" class="com.qcby.spring.ditest.Emp">
      <property name="ename" value="lucy"></property>
      <property name="age" value="20"></property>
    </bean>

    <bean id="emptwo" class="com.qcby.spring.ditest.Emp">
      <property name="ename" value="mary"></property>
      <property name="age" value="30"></property>
    </bean>

    <bean id="dept" class="com.qcby.spring.ditest.Dept">
      <property name="dname" value="技术部"></property>
      <property name="empList">
            <list>
                <ref bean="empone"></ref>
                <ref bean="emptwo"></ref>
            </list>
      </property>
    </bean>

</beans> 若为Set集合范例属性赋值,只需要将其中的list标签改为set标签即可  
https://i-blog.csdnimg.cn/direct/26bcb608cde149bb8474b7766c77d2d4.png
map集合范例

Student和Teacher类:
package com.qcby.spring.dimap;

import java.util.Map;

public class Student {
    private Map<String,Teacher> teacherMap;

    private String sid;
    private String sname;

    public void run(){
      System.out.println("学生编号:"+sid+"学生名称:"+sname);
      System.out.println(teacherMap);
    }


    public Map<String, Teacher> getTeacherMap() {
      return teacherMap;
    }

    public void setTeacherMap(Map<String, Teacher> teacherMap) {
      this.teacherMap = teacherMap;
    }

    public String getSid() {
      return sid;
    }

    public void setSid(String sid) {
      this.sid = sid;
    }

    public String getSname() {
      return sname;
    }

    public void setSname(String sname) {
      this.sname = sname;
    }
}
package com.qcby.spring.dimap;

public class Teacher {
    private String teacherId;
    private String teacherName;

    public String getTeacherId() {
      return teacherId;
    }

    public void setTeacherId(String teacherId) {
      this.teacherId = teacherId;
    }

    public String getTeacherName() {
      return teacherName;
    }

    public void setTeacherName(String teacherName) {
      this.teacherName = teacherName;
    }

    @Override
    public String toString() {
      return "Teacher{" +
                "teacherId='" + teacherId + '\'' +
                ", teacherName='" + teacherName + '\'' +
                '}';
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
      1.创建两个对象
      2.注入普通类型属性
      3.在学生bean注入map集合类型属性
    -->
    <bean id="teacherone" class="com.qcby.spring.dimap.Teacher">
      <!--注入普通类型属性-->
      <property name="teacherId" value="100"></property>
      <property name="teacherName" value="讲师1"></property>
    </bean>

    <bean id="teachertwo" class="com.qcby.spring.dimap.Teacher">
      <!--注入普通类型属性-->
      <property name="teacherId" value="200"></property>
      <property name="teacherName" value="讲师2"></property>
    </bean>

    <bean id="student" class="com.qcby.spring.dimap.Student">
      <!--注入普通类型属性-->
      <property name="sid" value="2000"></property>
      <property name="sname" value="李四"></property>
      <!--在学生bean注入map集合类型属性-->
      <property name="teacherMap">
            <map>
                <entry>
                  <!--key-->
                  <key>
                        <value>1</value>
                  </key>
                  <!--value为对象-->
                  <ref bean="teacherone"></ref>
                </entry>
                <entry>
                  <!--key-->
                  <key>
                        <value>2</value>
                  </key>
                  <!--value为对象-->
                  <ref bean="teachertwo"></ref>
                </entry>
            </map>
      </property>
    </bean>

</beans> https://i-blog.csdnimg.cn/direct/bd17857fcc9a49fa953aba123e968896.png
引用集合范例 

Lesson类:
package com.qcby.spring.dimap;

public class Lesson {
    private String lessonName;

    public String getLessonName() {
      return lessonName;
    }

    public void setLessonName(String lessonName) {
      this.lessonName = lessonName;
    }

    @Override
    public String toString() {
      return "Lesson{" +
                "lessonName='" + lessonName + '\'' +
                '}';
    }
}
package com.qcby.spring.dimap;

import java.util.List;
import java.util.Map;

public class Student {
    private List<Lesson> lessonList;

    private Map<String,Teacher> teacherMap;

    private String sid;
    private String sname;

    public void run(){
      System.out.println("学生编号:"+sid+"学生名称:"+sname);
      System.out.println(teacherMap);
      System.out.println(lessonList);
    }

    public List<Lesson> getLessonList() {
      return lessonList;
    }

    public void setLessonList(List<Lesson> lessonList) {
      this.lessonList = lessonList;
    }

    public Map<String, Teacher> getTeacherMap() {
      return teacherMap;
    }

    public void setTeacherMap(Map<String, Teacher> teacherMap) {
      this.teacherMap = teacherMap;
    }

    public String getSid() {
      return sid;
    }

    public void setSid(String sid) {
      this.sid = sid;
    }

    public String getSname() {
      return sname;
    }

    public void setSname(String sname) {
      this.sname = sname;
    }
}
使用util:list、util:map标签必须引入相应的命名空间  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
      1.创建三个对象
      2.注入普通类型属性
      3.使用util:类型定义
      4.在学生bean引入util:类型定义bean,完成list、map类型属性注入
    -->
    <bean id="lessonone" class="com.qcby.spring.dimap.Lesson">
      <property name="lessonName" value="java"></property>
    </bean>
    <bean id="lessontwo" class="com.qcby.spring.dimap.Lesson">
      <property name="lessonName" value="python"></property>
    </bean>

    <bean id="teacherone" class="com.qcby.spring.dimap.Teacher">
      <property name="teacherId" value="100"></property>
      <property name="teacherName" value="讲师1"></property>
    </bean>
    <bean id="teachertwo" class="com.qcby.spring.dimap.Teacher">
      <property name="teacherId" value="200"></property>
      <property name="teacherName" value="讲师2"></property>
    </bean>

    <bean id="student" class="com.qcby.spring.dimap.Student">
      <property name="sid" value="001"></property>
      <property name="sname" value="lucy"></property>
      <!--注入list、map类型属性-->
      <property name="lessonList" ref="lessonList"></property>
      <property name="teacherMap" ref="teacherMap"></property>
    </bean>
    <util:list id="lessonList">
      <ref bean="lessonone"></ref>
      <ref bean="lessontwo"></ref>
    </util:list>
    <util:map id="teacherMap">
      <entry>
            <key>
                <value>1001</value>
            </key>
            <ref bean="teacherone"></ref>
      </entry>
      <entry>
            <key>
                <value>1002</value>
            </key>
            <ref bean="teachertwo"></ref>
      </entry>
    </util:map>
</beans> https://i-blog.csdnimg.cn/direct/f4898b32f1344c2592773e8051dd811c.png
p命名空间

引入p命名空间:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd"> 引入p命名空间后,可以通过以下方式为bean的各个属性赋值:
<bean id="studentSix" class="com.qcby.spring6.bean.Student"
    p:id="1006" p:name="小明" p:clazz-ref="clazzOne" p:teacherMap-ref="teacherMap"></bean> 引入外下属性文件

1.加入依赖
<!-- MySQL驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>

<!-- 数据源 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.15</version>
</dependency> 2.创建外下属性文件
jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver 3.配置bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--引入外部属性文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--完成数据库信息注入-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
      <property name="url" value="${jdbc.url}"/>
      <property name="driverClassName" value="${jdbc.driver}"/>
      <property name="username" value="${jdbc.user}"/>
      <property name="password" value="${jdbc.password}"/>
    </bean>
</beans> 4.测试
package com.qcby.spring;

import com.alibaba.druid.pool.DruidDataSource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestJdbc {
    @Test
    public void demo(){
      ApplicationContext context = new ClassPathXmlApplicationContext("bean_jdbc.xml");
      DruidDataSource dataSource = context.getBean(DruidDataSource.class);
      System.out.println(dataSource.getUrl());
    }
}
https://i-blog.csdnimg.cn/direct/521e5b9774944ab4b9828b19acda50f8.png
bean的作用域

在Spring中可以通过配置bean标签的scope属性来指定bean的作用域范围,各取值含义到场下表:
取值含义创建对象的机遇singleton(默认)在IOC容器中,这个bean的对象始终为单实例IOC容器初始化时prototype这个bean在IOC容器中有多个实例获取bean时 如果是在WebApplicationContext环境下还会有另外几个作用域(但不常用):
取值含义request在一个哀求范围内有用session在一个会话范围内有用



演示:
1.创建Orders类
2.测试单实例:地址相同
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--通过scope属性配置单实例、多实例-->
    <bean id="orders" class="com.qcby.spring.scope.Orders"
    scope="singleton"></bean>
</beans> package com.qcby.spring;

import com.qcby.spring.scope.Orders;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestOrders {
    public static void main(String[] args) {
      ApplicationContext context =
                new ClassPathXmlApplicationContext("bean_scope.xml");
      Orders orders = context.getBean("orders", Orders.class);
      System.out.println(orders);
      Orders orders1 = context.getBean("orders", Orders.class);
      System.out.println(orders1);
    }
}
https://i-blog.csdnimg.cn/direct/eefcdf464c3e46e189bb6084adad3007.png
3.测试多实例:地址不同
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--通过scope属性配置单实例、多实例-->
    <bean id="orders" class="com.qcby.spring.scope.Orders"
    scope="prototype"></bean>
</beans> https://i-blog.csdnimg.cn/direct/8c5887f0c17f442293e9519d465c1c6f.png
bean的生命周期

1.bean对象创建(调用无参构造器)
2.给bean对象设置相关属性
3.bean的后置处理器(初始化之前)
4.bean对象初始化(需在配置bean时指定初始化方法)
5.bean的后置处理器(初始化之后)
6.bean对象就绪可以使用
7.bean对象销毁(需在配置bean时指定销毁方法)
8.IoC容器关闭
演示:
package com.qcby.spring.life;

public class User {
    private String name;

    //无参构造
    public User() {
      System.out.println("1.bean对象创建,调用无参构造");
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      System.out.println("2.给bean设置属性值");
      this.name = name;
    }

    //初始化的方法
    public voidinitMethod(){
      System.out.println("4.bean对象初始化,调用指定的初始化的方法");
    }

    //销毁的方法
    public void destroyMethod(){
      System.out.println("7.bean对象销毁,调用指定的销毁的方法");
    }



}
bean的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到IOC容器中,需要留意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中全部bean都会执行  
package com.qcby.spring.life;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;

public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("3.bean后置处理器,初始化之前执行");
      System.out.println(beanName+"::"+bean);
      return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("5.bean后置处理器,初始化之后执行");
      System.out.println(beanName+"::"+bean);
      return bean;
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.qcby.spring.life.User"
    scope="singleton" init-method="initMethod" destroy-method="destroyMethod">
      <property name="name" value="lucy"></property>
    </bean>

    <!-- bean的后置处理器要放入IOC容器才能生效 -->
    <bean id="myBeanProcessor" class="com.qcby.spring.life.MyBeanPost"/>
</beans> package com.qcby.spring;

import com.qcby.spring.life.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean_life.xml");
      User user = context.getBean("user", User.class);
      System.out.println("6.bean对象创建完成,可以使用");
      System.out.println(user);
      context.close();
    }
}
https://i-blog.csdnimg.cn/direct/ddee18650dbb4708b75ea222bb345b51.png
FactoryBean

FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean范例的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值。通过这种机制,Spring可以帮我们把复杂组件创建的具体过程和繁琐细节都屏蔽起来,只把最简便的使用界面展示给我们,未来我们整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的
演示:
package com.qcby.spring.factorybean;

import org.springframework.beans.factory.FactoryBean;

public class MyFactoryBean implements FactoryBean<User> {
    @Override
    public User getObject() throws Exception {
      return new User();
    }

    @Override
    public Class<?> getObjectType() {
      return User.class;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.qcby.spring.factorybean.MyFactoryBean"></bean>
</beans> package com.qcby.spring;

import com.qcby.spring.factorybean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser1 {
    public static void main(String[] args) {
      ApplicationContext context =
                new ClassPathXmlApplicationContext("bean_factorybean.xml");
      User user = (User) context.getBean("user");
      System.out.println(user);
    }
}
https://i-blog.csdnimg.cn/direct/0d2b5e22ebce4d61a707c6da245a1937.png
基于xml自动装配

自动装配:根据指定的计谋,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类范例或接口范例属性赋值
https://i-blog.csdnimg.cn/direct/f8c8010e6efd4622ab1fc6775992515d.png
使用bean标签的autowire属性设置自动装配结果
1.自动装配方式:byType(找的是class)
byType:根据范例匹配IOC容器中的某个兼容范例的bean,为属性自动赋值
若在IOC中,没有任何一个兼容范例的bean可以或许为属性赋值,则该属性不装配,即值为默认值null
若在IOC中,有多个兼容范例的bean可以或许为属性赋值,则抛出异常NoUniqueBeanDefinitionException
2.自动装配方式:byName(找的是id)
byName:将自动装配的属性的属性名,作为bean的id在IOC容器中匹配相对应的bean进行赋值
byType演示:
package com.qcby.spring.auto.controller;

import com.qcby.spring.auto.service.UserService;
import com.qcby.spring.auto.service.UserServiceImpl;

public class UserController {

    private UserService userService;

    public void setUserService(UserService userService) {
      this.userService = userService;
    }

    public void addUser(){
      System.out.println("controller中的方法执行了");
      //调用service的方法
      userService.addUserService();

    }
}
package com.qcby.spring.auto.service;

public interface UserService {
    public void addUserService();
}
package com.qcby.spring.auto.service;

import com.qcby.spring.auto.dao.UserDao;
import com.qcby.spring.auto.dao.UserDaoImpl;

public class UserServiceImpl implements UserService{
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
      this.userDao = userDao;
    }

    @Override
    public void addUserService() {
      System.out.println("userService中的方法执行了");
      //调用dao中的方法
      userDao.addUserDao();
    }
}
package com.qcby.spring.auto.dao;

public interface UserDao {
    public void addUserDao();
}
package com.qcby.spring.auto.dao;

public class UserDaoImpl implements UserDao{
    @Override
    public void addUserDao() {
      System.out.println("userDao中的方法执行了");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userController" class="com.qcby.spring.auto.controller.UserController"
          autowire="byType">
    </bean>

    <bean id="userService" class="com.qcby.spring.auto.service.UserServiceImpl"
          autowire="byType">
    </bean>

    <bean id="userDao" class="com.qcby.spring.auto.dao.UserDaoImpl"></bean>
</beans> package com.qcby.spring;


import com.qcby.spring.auto.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser1 {
    public static void main(String[] args) {
      ApplicationContext context =
                new ClassPathXmlApplicationContext("bean_auto.xml");
      UserController controller = context.getBean("userController", UserController.class);
      controller.addUser();
    }
}
https://i-blog.csdnimg.cn/direct/0c67b7f2e85a4acf82cd9e74a973f33b.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Spring3-IoC1-IoC容器、基于xml管理bean