• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

六千字长文体验Spring611种IOC控制反转实现方式

武飞扬头像
掘金小逆
帮助55

建议

接下来我们要学习一种新容器:IoC容器,即控制反转,我们在spring里面通过IoC容器管理java对象的实例化和初始化,我们将由IoC容器管理的java对象称为Spring Bean,这一点在和我们学javase中使用new来创建对象没有任何区别。(只是为了区分,在spring里面叫IoC罢了😉)

接下来我们要讲解一下什么是依赖注入,常见的依赖注入包括如下两种方式

  • set注入
  • 构造注入

我们在com.atguigu.spring6包下新建一个Person类,在User类中注入Person的属性,名为person

public class User {
    private String name ;
    private Person person ;
...
}

这里是初步实现注入的思想,后续我们会在spring源码部分进行详细讲解

为了对xml以及maven进行统一管理,我们将spring-first工程里面的maven坐标统一迁移到父工程Spring6中去

学新通技术网

📌最后不要忘记刷新maven

紧接着我们在Spring6中创建一个子工程,名为spring6-ioc-xml,继承父工程,JDK版本选择17,依旧是maven版本。

学新通技术网

初步配置见下图,不再赘述(bean.xml未进行配置)

学新通技术网

接着我们将log4j2.xmlspring-first工程中复制到spring6-ioc-xml下,并放入相对应的位置(如果不知道在哪里的请回看spring-first的创建过程☹)

我们在com.atguigu.spring6.iocxml包下新建一个class文件名为TestUser作为测试类进行测试。

然后我们对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.atguigu.spring6.iocxml.User"></bean>
</beans>

首先我们通过id来获取beanTestUser类配置内容如下

学新通技术网

运行结果如下

学新通技术网

第二种方式:我们可以根据类型获取bean

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

输出的结果与第一种方式无异

第三种方式:根据id和类型获取bean

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

输出的结果与第一、二种方式无异

📌当我们根据类型获取bean的时候,要求我们的IOC容器中指定类型的bean只能有一个

当我们在bean.xml中写入如下配置

<!--user对象创建-->
    <bean id="user" class="com.atguigu.spring6.iocxml.User"></bean>
    <bean id="user1" class="com.atguigu.spring6.iocxml.User"></bean>

我们在TestUser类中启动相关测试方法的时候,会发现报如下错误

Exception in thread "main" org.springframework.beans.factory.
NoUniqueBeanDefinitionException:
 No qualifying bean of type 'com.atguigu.spring6.iocxml.User' available:
 expected single matching bean but found 2: user,user1

这句话很明显的告诉我们:没有为com.atguigu.spring6.iocxml.User匹配到一个合适的对象,Spring6期望我们提供一个单实例的对象,但是我们却提供了两个,一个叫user,一个叫user1,因此报错。

接下来我们通过接口的方式去实现类获取的过程,首先我们在com.atguigu.spring6.iocxml包下新建一个package名为bean,分别建立UserDao接口以及UserDaoImpl实现类,内容如下

package com.atguigu.spring6.iocxml.bean;
public interface UserDao {
    public void run();
}
package com.atguigu.spring6.iocxml.bean;
public class UserDaoImpl implements UserDao{
    @Override
    public void run() {
        System.out.println("run.......");
    }
}

接着我们去配置一下bean.xml文件,我们同样是通过idclass属性去获取我们所要得到的实现类,以验证IOC反转控制的思想

<!--一个接口实现类获取过程-->
    <bean id="UserDaoImpl" class="com.atguigu.spring6.iocxml.bean.UserDaoImpl"></bean>

最后我们在package包下新建一个测试类名为TestUserDao,写入下方代码

package com.atguigu.spring6.iocxml.bean;
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下新建一个类叫PersonDaoImpl,并将它继承于UserDao接口。

package com.atguigu.spring6.iocxml.bean;

public class PersonDaoImpl implements UserDao{
    @Override
    public void run() {
        System.out.println("person run.....");
    }
}

然后我们去bean.xml中进行配置接口所对应的bean标签

<!--一个接口实现多个类的过程-->
    <bean id="PersonDaoImpl" class="com.atguigu.spring6.iocxml.bean.PersonDaoImpl"></bean>

最后我们再对TestUserDao进行测试,报错信息如下

Exception in thread "main" org.springframework.beans.factory.
NoUniqueBeanDefinitionException: 
No qualifying bean of type 'com.atguigu.spring6.iocxml.bean.UserDao' available: 
expected single matching bean but found 2: UserDaoImpl,PersonDaoImpl

很明显,报错原因是因为bean不唯一。

接下来我们通过set方法注入。首先我们在com.atguigu.spring6.iocxml下新建一个package名为di,新建一个类名为Book,内容如下

package com.atguigu.spring6.iocxml.di;

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

    public String getBname() {
        return bname;
    }

    public void setBname(String bname) {
        this.bname = bname;
    }

    public String getAuthor() {
        return author;
    }

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

    public static void main(String[] args) {
//        set方法注入
        Book book = new Book();
        book.setBname("java");
        book.setAuthor("尚硅谷");
    }
}

根据上方代码块我们可以得知,我们通过setter的途径去对Book对象注入相关属性,这是我们最常见的set注入,接下来我们另一种set注入方法。

首先先对Book类添加相关构造器

public Book() {
    }

public Book(String bname, String author) {
        this.bname = bname;
        this.author = author;
    }

通过New对象的方式进行注入

//        通过构造器注入
        Book book1 = new Book("c  ","尚硅谷");

接下来介绍Spring6中特有的set注入方法。我们在resources下新建一个xml名为bean-di,具体配置内容见下方代码块

<!--1.set方法注入-->
    <bean id="book" class="com.atguigu.spring6.iocxml.di.Book">
        <property name="bname" value="前端开发"></property>
        <property name="author" value="尚硅谷"></property>
    </bean>

在这个xml中,我们引入一个新的标签名为property,其中name属性的值与你在Book中写入的变量有关,value的值即为上文set方法注入的属性拥有同等效力。

然后我们在Book类中写入toString()方法,用于打印输出相关信息。接着我们在di中写入测试类,相关测试信息与之前无异,读者仿照前文自行写入测试类即可,测试结果如下

学新通技术网

接下来我们尝试一下构造器注入

首先我们去xml中进行配置

<!--2.构造器注入-->
    <bean id="bookCon" class="com.atguigu.spring6.iocxml.di.Book">
        <constructor-arg name="bname" value="java开发"></constructor-arg>
        <constructor-arg name="author" value="尚硅谷"></constructor-arg>
    </bean>

在上方代码块中,我们引入了一个新标签名为constructor-arg,该bean标签有两个属性,与property一致。然后我们在Book的含参构造器中写入如下输出语句

System.out.println("有参数构造执行了.....");

接着我们在TestBook中写入测试类,原理与上文一致,读者自行编写测试类即可,测试结果如下

学新通技术网

📌我们在xml中构造bean标签中constructor-arg的时候,它还有一个属性叫作index,读者可自行摸索并写出测试方法,测试结果与上图一致。

接下来我们要对一个特殊值:null进行处理。首先我们在Book中新建变量others使其私有化,属性为String,为它生成set方法以及在Book内重新生成toString()。接着我们在xml文件中手写property,内容见下

<property name="others"><null/></property>

这一方面很好的处理value值为null的情况。

有时候我们会在xml文件中写入特殊符号,比如<>,此时我们就需要特殊转义符号来进行处理。

<property name="others" value="&lt;"></property>

最后一种情况,有时候我们想在xml文件中注入纯文本,此时我们需要用到CDATA节,具体使用方法见下

<property name="others">
            <value><![CDATA[a < b]]></value>
        </property>

要想为对象类型属性赋值,我们首先得做一下准备工作。首先我们要在com.atguigu.spring6.iocxml包下新建一个package名为ditest,分别新建类名为DeptEmp两个文件,分别写入如下内容

package com.atguigu.spring6.iocxml.ditest;

public class Dept {
    private String dname;
    public void info(){
        System.out.println("部门名称:"   dname);
    }
}
package com.atguigu.spring6.iocxml.ditest;

public class Emp {
//    员工属于某个部门
    private Dept dept;
    private String ename;
    private Integer age;
    public void work(){
        System.out.println("emp is working....."   age);
    }
}

接下来我们分别在两个类中注入getset方法,并且在Emp中将work方法改写为

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

接着我们新建一个xml名为bean-ditest,在xml中,我们先对Dept进行普通的属性注入,id值均为类名小写,property值见下

<property name="dname" value="安保部"></property>

和上述操作一样,我们同样为Emp注入相关属性

<property name="ename" value="lucy"></property>
<property name="age" value="18"></property>

接下来我们要注入对象类型的属性,写法如下

<property name="dept" ref="dept"></property>

ref代表引入的意思,表示引入我们的对象,这个对象与Dept进行属性注入的时候的id值拥有同等效力。我们在ditest下新建一个测试类名为TestEmp,读者对Emp自行编写测试方法并且调用work方法,结果如下

学新通技术网

接下来我们使用内部bean的方式进行注入,首先编写我们的xml文件,内容如下

<!--第二种方式:内部bean做注入-->
    <bean id="dept2" class="com.atguigu.spring6.iocxml.ditest.Dept">
        <property name="dname" value="财务部"></property>
    </bean>
    <bean id="emp2" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <!--普通属性注入-->
        <property name="ename" value="mary"></property>
        <property name="age" value="20"></property>
<!--使用内部bean的方式进行注入-->
        <property name="dept">
            <bean id="dept2" class="com.atguigu.spring6.iocxml.ditest.Dept">
                <property name="dname" value="财务部"></property>
            </bean>
        </property>
    </bean>

xml中我们可以看到,我们使用内部bean进行了注入,具体操作是在property中注入bean,这也是为什么叫内部bean的原因,换句话说,现在我们是在emp2中注入内部bean,相比以前单独的两个模块,能更直观、方便的看到注入关系。最后读者对Emp自行编写测试方法并且调用work方法,结果如下

学新通技术网

接下来我们要介绍第三种方法:级联赋值。首先我们对xml文件进行修改,内容见下

<!--第三种方式:级联赋值-->
    <bean id="dept3" class="com.atguigu.spring6.iocxml.ditest.Dept">
        <property name="dname" value="技术研发部"></property>
    </bean>
    <bean id="emp3" class="com.atguigu.spring6.iocxml.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>

我们重点可以放在最后一行代码上,我们通过类调属性的方式对dname的值进行修改,根据就近原则,控制台打印输出的结果也应该是跟测试部有关,然后读者对Emp自行编写测试方法并且调用work方法,结果如下

学新通技术网

接着我们尝试着去注入数组类型的相关属性,首先我们新建一个xml名为bean-diarray,相关配置见下

<!--注入数组类型的属性-->
    <bean id="dept" class="com.atguigu.spring6.iocxml.ditest.Dept">
        <property name="dname" value="技术部"></property>
    </bean>
    <bean id="emp" class="com.atguigu.spring6.iocxml.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>Java</value>
                <value>Vue</value>
                <value>MySQL</value>
            </array>
        </property>
    </bean>

我们重点关注<array>相关标签的代码,因为我们考虑到人的爱好不止一个,所以Spring6为我们提供了一个内置的array标签,在标签内我们可以写入多个值。接着我们在Emp中对work方法进行改写,内容如下

public void work(){
        System.out.println("emp is working....."   age);
        dept.info();
        System.out.println(Arrays.toString(loves));
    }

最后读者对Emp自行编写测试方法并且调用work方法,结果如下

学新通技术网

下面我们介绍一下list集合的注入,首先我们在Dept中写入一个集合,并且对info进行改写,内容如下

private List<Emp> empList;

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

接着我们新建xml名为bean-dilist,内容如下

<bean id="empone" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <property name="ename" value="lucy"></property>
        <property name="age" value="19"></property>
    </bean>
    <bean id="emptwo" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <property name="ename" value="mary"></property>
        <property name="age" value="30"></property>
    </bean>
    <bean id="dept" class="com.atguigu.spring6.iocxml.ditest.Dept">
    <property name="dname" value="技术部"></property>
    <property name="empList">
        <list>
            <ref bean="empone"></ref>
            <ref bean="emptwo"></ref>
        </list>
    </property>
</bean>

我们重点关注<list>,在list集合中,我们引入相关ref,表示对属性的注入。最后读者对Dept自行编写测试方法并且调用info方法,结果如下

学新通技术网 现在我们试着进行map集合的注入,步骤如下。首先我们在com.atguigu.spring6.iocxml下新建一个package名为dimap,在dimap中新建两个文件,分别为StudentTeacher,分别创建如下属性

public class Student {
    private Map<String,Teacher> teacherMap;
    private String sid ;
    private String sname ;
......
}
public class Teacher {
    private String teacherId;
    private String teacherName;
......
}

我们分别对这两个类注入setgettoString方法,接下来我们编写xml文件,名为bean-dimap,在xml文件中,我们主要有以下三个步骤

  • 创建两个对象
  • 注入普通类型的属性
  • 在学生的bean中注入map集合类型的属性

前两个读者自行理解并对xml进行相关操作,我们重点讲解第三个如何实现。我们对teacherMap这个map进行如下操作

<property name="teacherMap">
            <map>
                <entry>
                    <key>
                        <value>10010</value>
                    </key>
                    <ref bean="teacher"></ref>
                </entry>
            </map>
        </property>

在上方代码块中,我们通过引入entry标签对map进行操作,同样是通过value以及ref属性对map注入相关值,由于我们的map是写入Teacher类中,所以我们ref引入的值必须是teacher

接着我们在Student类中对run方法进行改写,内容如下

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

读者可自行在xml中写入两个map注入属性,并在dimap中新建测试类TestStu,读者自行完成即可。运行结果如下

学新通技术网

接下来我们尝试着引用集合类型的bean,首先我们在dimap中新建类为Lesson,在类中我们写入一个属性名为lessonNameString类型且私有化,并且构造出它的getsettoString方法。

接下来我们新建一个xml名为bean-diref,我们要完成的步骤如下

  • 创建三个对象
  • 注入普通类型属性
  • 使用util:类型 定义
  • 在学生bean里面引入util:类型定义bean,完成list 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/beans/spring-util.xsd>
       <http://www.springframework.org/schema/beans>
       <http://www.springframework.org/schema/beans/spring-beans.xsd>">

接下来我们就可以引入util标签进行引用集合类型的注入。首先我们将idstudentproperty属性补充完整,然后引入util标签,内容见下

<util:list id="lessonList">
<ref bean="lessonone"></ref>
<ref bean="lessontwo"></ref>
    </util:list>
    <util:map id="teacherMap">
        <entry>
            <key>
                <value>10010</value>
            </key>
            <ref bean="teacherone"></ref>
        </entry>
        <entry>
            <key>
                <value>10086</value>
            </key>
            <ref bean="teachertwo"></ref>
        </entry>
    </util:map>

按照上述步骤,读者可自行编写测试类,不出意外会报错(故意留的😋😋),我们需要在xml修改相关配置,改动地方见下图

学新通技术网

运行成功截图见下

学新通技术网

接下来我们介绍p标签命名注入,首先我们在beans头标签中写入

xmlns:p="<http://www.springframework.org/schema/p>"

然后我们写入如下标签

<!--p命名空间注入-->
    <bean id="studentp" class="com.atguigu.spring6.iocxml.dimap.Student"
    p:sid="100" p:sname="mary" p:lessonList-ref="lessonList" p:teacherMap-ref="teacherMap">
    </bean>

我们通过引入外部属性文件的方式对数据进行注入处理,首先我们在pom.xml中引入相关依赖

<dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.30</version>
    </dependency>
    <!-- <https://mvnrepository.com/artifact/com.alibaba/druid> -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.0.31</version>
    </dependency>

接着我们在resources下新建一个properties名为jdbc,写入内容如下

jdbc.user=root
jdbc.password=20020930pch
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver

📌数据库使用的是8.0及以上的版本

我们新建一个xml文件名为bean-jdbc,并且使用context命名空间引入,内容如下

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

接下来我们在com.atguigu.spring6.iocxml中新建一个package名为jdbc,在里面新建一个测试类名为TestJdbc,内容如下

package com.atguigu.spring6.iocxml.jdbc;

import com.alibaba.druid.pool.DruidDataSource;
import org.junit.jupiter.api.Test;

public class TestJdbc {
    @Test
    public void demo1(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("20020930pch");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    }
}

然后我们完成数据库相关信息的注入,使用$引用properties文件中的相关属性

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

最后我们写入一个测试类,方法如下

@Test
    public void demo2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-jdbc.xml");
        DruidDataSource dataSource = context.getBean(DruidDataSource.class);
        System.out.println(dataSource.getUrl());
    }

接下来我们测试bean的作用域。我们先在com.atguigu.spring6.iocxml中新建一个package名为scope,在包下我们新建Orders测试类,然后在resources中新建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>">
<!--通过scope属性配置单实例/多实例-->
<bean id="orders" class="com.atguigu.spring6.iocxml.scope.Orders" scope="singleton">

</bean>
</beans>

xml文件中我们可以看到在bean标签内多了一个属性叫作scope,读者在这里可以把它理解为作用域标签,Spring6在默认情况下是单实例,如果想设置多实例,在scope里面修改即可。最后读者自行编写测试类进行测试,并调用sout方法输出orders

接下来我们介绍一下bean的生命周期。首先我们在com.atguigu.spring6.iocxml中新建一个package名为life,在life中新建一个User类,内容如下

package com.atguigu.spring6.iocxml.life;

public class User {
    private String name ;
//    无参数的构造
    public User(){
        System.out.println("1 bean对象创建,调用无参构造");
    }
//  初始化的方法
    public void initMethod(){
        System.out.println("4 bean对象初始化 调用指定的初始化的方法");
    }
//  销毁的方法
    public void destoryMethod(){
        System.out.println("7 bean对象销毁 调用指定的销毁的方法");
    }
    public String getName() {
        return name;
    }

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

接着我们去xml文件中进行配置,新建一个xml名为bean-life,在文件中我们写入如下内容

<?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.atguigu.spring6.iocxml.life.User"
          scope="singleton" init-method="initMethod" destroy-method="destoryMethod">
        <property name="name" value="lucy"></property></bean>
</beans>

最终我们在life下新建一个测试类名为TestUser,用来测试bean的生命周期,内容见下图

package com.atguigu.spring6.iocxml.life;

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-life.xml");
        User user = context.getBean("user", User.class);
        System.out.println("6 bean对象创建完成了,可以使用了");
        System.out.println(user);
//        context.close();    // 销毁
    }
}

测试完毕之后我们写入如下方法进行测试,目的是为了调用context.close();

package com.atguigu.spring6.iocxml.life;

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

如此下来,bean的基本生命周期就算走了一遍,读者可自行阅读代码加深印象。

细心的读者可以发现,生命周期的结果显示并不完整,接下来我们把完整的生命周期展示一遍。首先我们在life下新建一个类名为MyBeanPost,我们在这个类中接入BeanPostProcessor接口,在接口中我们能看到两个方法,我们将这两个方法在MyBeanPost中进行重写,声明为public,并且分别加上bean生命周期中的3和5,最终进行测试,结果如下

学新通技术网

接下来我们基于XML管理Bean-FactoryBean,首先我们新建一个package名为factorybean,然后我们分别创建两个对象,名为FactoryBeanUser(创建User是因为有泛型),我们在FactoryBean中写入如下内容

package com.atguigu.spring6.iocxml.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名为bean-factorybean,我们在里面注入iduser的属性,并编写测试类进行测试。

📌在编写测试类的时候,读者需要注意使用强转,因为我们的方法在FactoryBean是通过User创建的。

接下来我们尝试基于XML管理Bean实现自动装配。首先我们在com.atguigu.spring6.iocxml下新建一个package名为auto,在其包下新建三个package分别名为controllerdaoservice。然后我们在dao层下新建一个interface名为UserDao,配置内容如下

package com.atguigu.spring6.iocxml.auto.dao;

public interface UserDao {
    public void addUserDao();
}

接着我们创建一个实现类名为UserDaoImpl并且继承UserDao,实现方法的重写,内容如下

@Override
    public void addUserDao() {
        System.out.println("userDao方法执行了...");
    }

以此类推,请读者自行在service层下写入相关信息。接着在UserController中写入如下信息

package com.atguigu.spring6.iocxml.auto.controller;

import com.atguigu.spring6.iocxml.auto.service.UserService;
import com.atguigu.spring6.iocxml.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();
    }
}

完成上述步骤之后,我们在resources中写入XML名为bean-auto,读者自行对三个id属性进行相关配置,其中在userControlleruserService中写入如下标签以实现根据类型实现自动装配

autowire="byType"

最终读者自行编写与userController相关的测试类并进行测试。

以上方法是根据类型实现自动装配,在Spring6中,我们还可以根据名称实现自动装配,即将上述标签替换成

autowire="byName"

运行结果与上述是一致的,区别在于:当我们使用byName注入属性的时候,我们id的名字必须与测试类中getBean中的名字一致,否则报错显示userDaonull,而类型注入可以忽略这一点。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanffhia
系列文章
更多 icon
同类精品
更多 icon
继续加载