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

news2024/11/24 4:35:36

目录

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

②方式二:根据类型获取

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

当根据类型获取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);

    }
}

扩展:

如果组件类实现了接口,根据接口类型可以获取 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();
    }
}

如果一个接口有多个实现类,这些实现类都配置了 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);
    }

}

构造器注入

第一步:创建类,定义属性,生成有参构造方法

第二步:在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);
    }

特殊值处理

字面量赋值

什么是字面量?

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><![CDATA[a < b]]></value>
</property>

特殊类型属性注入

对象类型属性注入

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>

方式二:内部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>

方式三:级联属性赋值
    <!--方式三:级联赋值-->
    <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>

数组类型属性注入

员工类:

    //爱好
    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>

集合类型属性注入

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标签即可  

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>

引用集合类型 

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>

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());
    }
}

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

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>

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 void  initMethod(){
        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();
    }
}

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

基于xml自动装配

自动装配:根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类类型或接口类型属性赋值

使用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();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设背包密码系统的超递增序列为A=(3,4,9,17,35),乘数t=19,模数k=73,试对good night加密

PS:后续在此基础上更新Java代码 1.超递增序列含义 超递增序列是指一个正整数序列&#xff0c;其中每个元素a[i]&#xff08;i≥2&#xff09;都大于它前面所有元素之和&#xff0c;即a[i] > &#xff08;a[1] a[2] ... a[i-1]&#xff09; 2.加密公式 C&#xff08; B…

html+css+js网页设计 旅游 大理旅游7个页面

htmlcssjs网页设计 旅游 大理旅游7个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#…

信通院发布首个《大模型媒体生产与处理》标准,阿里云智能媒体服务作为业界首家“卓越级”通过

中国信通院近期正式发布《大模型驱动的媒体生产与处理》标准&#xff0c;阿里云智能媒体服务&#xff0c;以“首批首家”通过卓越级评估&#xff0c;并在9大模块50余项测评中表现为“满分”。 当下&#xff0c;AI大模型的快速发展带动了爆发式的海量AI运用&#xff0c;这其中&a…

异构仿真:打造更可靠的综合化航空电子软件

综合化航空电子系统是一类典型的安全关键系统&#xff0c;具有分布式、异构、计算资源和物理资源强耦合等特征。随着IMA&#xff08;Integrated Modular Avionics&#xff0c;综合模块化航空电子&#xff09;系统趋于复杂化和智能化&#xff0c;系统的功能越来越多地采用软件来…

权威认可,信源信息再次斩获国家发明专利

近日&#xff0c;郑州信源信息技术股份有限公司&#xff08;简称“信源信息”&#xff09;继获得“一种安全认证方法及系统”发明专利后&#xff0c;再次喜获国家知识产权局颁发的发明专利“适用于多环境OFD文档的投标文件处理方法及系统”。本次发明专利的获得&#xff0c;不仅…

华为云ROMA Connect聚焦创新,在Gartner®峰会发布智能集成新视角

9月9日-9月10日&#xff0c;Gartner全球应用创新及商业解决方案峰会在伦敦举行&#xff0c;围绕企业应用策略、智能平台工程和生成式AI&#xff0c;来自全球的1700业内专家共同探讨新趋势带来的机遇和挑战。华为云ROMA Connect发表 “人工智能”主题演讲之一&#xff0c;展现新…

黑龙江等保测评二级系统费用解析:如何合理预算?

在信息安全日益受到重视的今天&#xff0c;等保测评成为企业合规的重要环节。尤其是在黑龙江&#xff0c;随着网络安全法的实施&#xff0c;越来越多的企业开始关注等保测评的相关费用。那么&#xff0c;黑龙江等保测评二级系统的费用是如何计算的呢&#xff1f; 首先&#xf…

linux 定时将固态硬盘数据备份至机械硬盘

需求背景 为了加强公司数据的安全性和可靠性&#xff0c;我们将实施一项数据备份策略。该策略涉及将服务器上的固态硬盘&#xff08;SSD&#xff09;中的关键数据定期备份到机械硬盘&#xff08;HDD&#xff09;上。这一过程旨在保护数据免受意外删除、硬件故障或其他潜在风险…

【诉讼流程-健身房-违约认定-私教课-诉讼书前提材料整理-民事诉讼-自我学习-铺平通往法律的阶梯-讲解(2)】

【诉讼流程-健身房-违约-私教课-前期法律流程-民事诉讼-自我学习-铺平通往法律的阶梯-讲解&#xff08;2&#xff09;】 &#xff08;1&#xff09;前言说明1、目的2、一个小测试1、更换原教练2、频繁更换教练3、上课估计拖课&#xff0c;占用上课时间&#xff0c;抽烟等。4、以…

VMware Workstation Pro 17 提供个人版使用

说明 VMware 下载链接已经合并到博通网站&#xff0c;原有网站已停用。 注册 注册并登录博通网站&#xff0c;即可下载软件&#xff0c;不过注册有很多限制 建议使用国外的邮箱。 我是用gmail注册的。 下载 https://support.broadcom.com/group/ecx/productdownloads?subf…

JavaScript 基础 - 第16天_AJAX入门

文章目录 Day01_Ajax入门目录学习目标01.AJAX 概念和 axios 使用目标讲解小结 02.认识 URL目标讲解小结 03.URL 查询参数目标讲解小结 04.案例-查询-地区列表目标讲解小结 05.常用请求方法和数据提交目标讲解小结 06.axios 错误处理目标讲解小结 07.HTTP 协议-请求报文目标讲解…

iOS 知识点记录

王巍 博客地址&#xff1a;OneVs Den git地址&#xff1a;onevcat (Wei Wang) GitHub 江湖人称喵神&#xff0c;目前就职于line。喵神的博客涉及方面比较广, 有Obejctive-C, Swift, SwiftUI, Unity等等。博客内容很有深度&#xff0c;非常值得关注。 戴铭 博客地址&#xff1…

Springboot项目打war包运行及错误解决

一,打war包 1. 修改pom.xml 为了不影响原pom.xml, 我复制了一个文件叫pom_war.xml , 需要打war包就采用pom_war.xml进行打war包, 你也可以直接修改pom.xml ① 打包方式改为war 没有就增加此配置 <packaging>war</packaging> ② 排除内嵌tomcat依赖 <de…

Android Studio 安装2022版稳定版 2022.3.1 详细操作(带图展示)

一、先规范好文件地址 分别创建文件夹Android_SDK和AndroidStudio用来放置SDK与软件 特别注意&#xff1a;文件夹不要出现空格与中文&#xff0c;且文件夹都为空 二、下载android studio &#xff08;1&#xff09;点开下载网页 https://developer.android.google.cn/studi…

定时任务和延时任务

目录 一、延时任务 2.at任务的黑白名单 二、定时任务 1.系统定时任务 三、系统中临时文件的管理方式 一、延时任务 [rootlocalhost ~]# at 23:37 ##设定任务执行时间 at> rm -fr /mnt/* ##任务动作 at> << CTRL D ##用ctrlD发起任务 [rootlocalhost ~]# at no…

36岁,大厂女程序员,中年失业后,我开始接受自己的平凡,并深耕自己

作为80后秦岭大山里面的穷苦农民工家的孩子&#xff0c;从小因为讨厌做家务&#xff0c;做农活&#xff0c;而且家里孩子众多&#xff0c;物质匮乏&#xff0c;从小就特别渴望走出大山。 上学的时候&#xff0c;通过刻苦努力&#xff0c;成绩也还算可以&#xff0c;经常受到老师…

系统架构设计师教程 第5章 5.1 软件工程 笔记

5.1 软件工程 ★★★★☆ 5.1.1 软件工程定义 软件工程过程是指为获得软件产品&#xff0c;在软件工具的支持下由软件工程师完成的一系列软件工程活动&#xff0c;包括以下4个方面。 (1)P(Plan)——软件规格说明。规定软件的功能及其运行时的限制。 (2)D(Do) — —软件开发。开…

成功晋级 | 3本ELSEVIER期刊正式被ESCI收录,最快的录用后2天即可出版

爱思唯尔&#xff08;ELSEVIER&#xff09;作为一家国际顶尖出版集团&#xff0c;自1880年创办以来&#xff0c;旗下出版期刊有2800多种&#xff0c;其中包含《柳叶刀》《细胞》等TOP期刊&#xff0c;在学术科研界享誉盛名。 根据八月份公布的最新SCI目录显示&#xff0c;ELSE…

基于单片机的水情监测站设计

本设计以STM32单片机为控制核心&#xff0c;利用DS18B20温度检测模块&#xff0c;TSW-30浊度传感器&#xff0c;PH值传感器&#xff0c;完成对水环境温度&#xff0c;水浊度&#xff0c;PH值的检测。系统使用OLED12864作为系统显示模块&#xff0c;使用WiFi模块来实现对监测数据…

GPU池化如何帮助用户灵活“避坑”

随着5G、人工智能、云计算、大数据、IoT等技术的推动&#xff0c;万物互联的时代即将到来。因为大量AI应用都依赖GPU的超强计算能力&#xff0c;可以预见算力需求将越来越大&#xff0c;GPU在数据中心的地位也会越来越高。 然而理想是丰满的&#xff0c;现实却是骨感的&#x…