【Spring】XML方式实现(无参构造 有参构造)和注解方式实现 IoC


简单记录 Spring5企业级开发实战 周冠亚,黄文毅著- 和 Spring5最新完整教程IDEA版-秦疆

Spring IoC的实现方式

IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象(容器中获取Bean)。

container magic

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

一个程序、对象创建方式、配置说明

导入Jar包

注 : spring 需要导入commons-logging进行日志记录 . 我们利用maven , 他会自动下载对应的依赖项 .

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.22.RELEASE</version>
</dependency>

https://repo.spring.io/release/org/springframework/spring/

创建一个空白maven项目实现IoC。

XML方式实现

XML方式实现用构造器方式实现IoC分为无参构造器和有参构造器两种。

通过无参构造方法来创建

User使用无参构造器的方式,实现无参构造器的IoC。

1、编写一个User实体类

User类的实现如下:

User.java

package com.test.ioc.xml;

/**
 * 无参构造器实现IoC
 */
public class User  {
    /**
     * 姓名
     */
    private String name;
    /**
     * 无参构造器
     */
    public User () {
        System.out.println("user无参构造方法");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
    /**
     * 显示姓名
     */
    public void showName(){
        System.out.println("我叫 " + name +",哈哈!");
    }
    /**
     * 说话的方法
     */
   
    public void say() {
        System.out.println("大家好!");
    }
}


2、编写我们的spring文件

编写我们的spring文件 , 这里我们命名为spring-chapter2.xml

在resources下spring-chapter2.xml文件中,通过bean标签将User类交给IoC容器管理,代码如下:

<?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就是java对象 , 由Spring创建和管理-->
    <!-- User无参构造器 -->
    <bean id="user" class="com.test.ioc.xml.User">
        <property name="name" value="柳小子"/>
    </bean>

</beans>

3、测试类 UserTest.java

我们可以去进行测试了,哈哈

UserTest.java

package ioc.xml;

import com.test.ioc.xml.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author Liu Awen Email:[email protected]
 * @create 2020-01-14 9:47 AM
 */
public class UserTest {
    @Test
    public void test(){
         //解析beans.xml文件 , 生成管理相应的Bean对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-chapter2.xml");
         //getBean : 参数即为spring配置文件中bean的id .
        User user = (User) context.getBean("user");
        user.say();
        user.showName();
    }
}

4、测试结果

D:\Environments\jdk-11.0.2\bin\java.exe...

user无参构造方法
大家好!
我叫 柳小子,哈哈!



Process finished with exit code 0

结果可以发现,在调用showName方法之前,User对象已经通过无参构造初始化了!

User使用无参构造器的方式,实现无参构造器的IoC。

OK , 到了现在 , 我们彻底不用再去程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 , 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !

思考

  • user 对象是谁创建的 ?

    【 user 对象是由Spring创建的 】

  • user 对象的属性是怎么设置的 ?

    【user 对象的属性是由Spring容器设置的 】

这个过程就叫控制反转(IoC) :

  • 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的
  • 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .

依赖注入 : 就是利用set方法来进行注入的.

IOC是一种编程思想,由主动的编程变成被动的接收

可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .

通过有参构造方法来创建

与User类不同的是,Order类是没有无参构造器的,Order类含有一个带有两个参数——订单号和订单金额的有参构造器。

1、Order.java

Order类的定义如下:

package com.test.ioc.xml;

/**
 * 有参构造器实现IoC
 */
public class Order implements Deliverable {
    /**
     * 订单号
     */
    private long orderId;
    /**
     * 订单金额
     */
    private double amount;

    /**
     * 有参构造器
     * @param orderId
     * @param amount
     */
    public Order (long orderId, double amount) {
        this.orderId = orderId;
        this.amount = amount;
    }

    public long getOrderId() {
        return orderId;
    }

    public void setOrderId(long orderId) {
        this.orderId = orderId;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderId=" + orderId +
                ", amount=" + amount +
                '}';
    }

    /**
     * 订单发货方法
     */
    @Override
    public void delivery() {
        System.out.printf("订单号%s,金额%s,已发货!", orderId, amount);
    }
}

interface 接口 Deliverable

package com.test.ioc.xml;

public interface Deliverable {
    /**
     * 发货
     */
    void delivery();
}

2、spring-chapter2.xml

在spring-chapter2.xml文件中通过bean标签将User类交给IoC容器管理。具体配置如下:

 <?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">

   <!--Order有参构造器-->
    <bean id="order" class="com.test.ioc.xml.Order">
        <constructor-arg index="0" value="202001141004"/>
        <constructor-arg index="1" value="8888"/>
    </bean>

</beans>

*.xml 有三种方式编写

<!-- 第一种根据index参数下标设置 -->
<bean id="order" class="com.test.ioc.xml.Order">
    <!-- index指构造方法 , 下标从0开始 -->
    <constructor-arg index="0" value="202001141004"/>
     <constructor-arg index="1" value="8888"/>
</bean>
<!-- 第二种根据参数名字设置 -->
<bean id="order" class="com.test.ioc.xml.Order">
    <!-- name指参数名 -->
    <constructor-arg name="orderId" value="202001141004"/>
    <constructor-arg name="amount" value="8888"/>
</bean>
<!-- 第三种根据参数类型设置 -->
<bean id="order" class="com.test.ioc.xml.Order>
    <constructor-arg type="java.lang.Long" value="202001141004"/>
  <constructor-arg type="java.lang.Double" value="8888"/>                                             </bean>

3、测试类 OrderTest.java

在单元测试类OrderTest中,通过依赖注入得到Deliverable的对象Order,单元测试代码如下:

package ioc.xml;

import com.test.ioc.xml.Deliverable;
import com.test.ioc.xml.Speakable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * 测试XML方式的IoC
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-chapter2.xml")
public class XmlTest {
    //Spring 容器注入依赖的Speakable对象
    @Autowired
    private Speakable speakable;
    //Spring 容器注入依赖的Deliverable对象
    @Autowired
    private Deliverable deliverable;
    @Test
    public void test() {
        speakable.say();
        deliverable.delivery();
    }
}

其中@RunWith这个注解指定了让单元测试运行于Spring的环境中,@ContextConfiguration这个注解指定Spring加载的配置文件。

4、测试结果

执行单元测试,测试结果如下。

D:\Environments\jdk-11.0.2\bin\java.exe...

订单号202001141004,金额8888.0,已发货!
Order{orderId=202001141004, amount=8888.0}



Process finished with exit code 0

结论:在配置文件加载的时候。其中管理的对象都已经初始化了!

Order使用有参构造器的方式,实现有参构造器的IoC。

通过注解方式实现

除了通过构造器实现IoC,还可以通过Spring提供的注解方法实现IoC,这也是企业开发过程中最常用的一种IoC实现方式。

1、编写一个Student实体类

下面通过学生类Student阐述注解的方式实现IoC。

接口 HomeWork.java

package com.test.ioc.annotation;

public interface HomeWork {
    /**
     * 写家庭作业
     */
    void doHomeWork();
}

Student类的定义如下:

package com.test.ioc.annotation;

import org.springframework.stereotype.Service;

@Service
public class Student implements HomeWork {
    /**
     * 写家庭作业
     */
    @Override
    public void doHomeWork() {
        System.out.println("我是学生,我要写家庭作业");
    }
}

注意此时的Student类上加了一个@Service注解,这告诉Spring,让其管理这个类的对象,因此开发人员就不再需要管理Student对象了。

2、编写我们的spring文件

与XML方式实现的IoC不同的是,注解方式除了配置@Service注解外,还需要指定Spring对需要管理的bean目录,否则Spring不能定位其需要管理的bean。具体配置如下:

<!--spring 管理的bean的路径-->
    <context:component-scan base-package="com.test.ioc"></context:component-scan>

spring-chapter2.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">
	 
    <!--spring 管理的bean的路径-->
    <context:component-scan base-package="com.test.ioc"></context:component-scan>

</beans>

3、依赖注入,将对象注入到测试类中

接下来在测试类AnnotationTest中通过依赖注入,将HomeWork对象注入到AnnotationTest测试类中,测试代码如下:

package ioc.annotation;

import com.test.ioc.annotation.HomeWork;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * 测试注解方式的IoC
 */
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:spring-chapter2.xml")
public class AnnotationTest {
    @Autowired
    private HomeWork homeWork;
    //Spring 容器注入依赖的Deliverable对象
    @Test
    public void test() {
        homeWork.doHomeWork();
    }
}

4、测试结果

运行单元测试,测试结果如下:

D:\Environments\jdk-11.0.2\bin\java.exe 

我是学生,我要写家庭作业



Process finished with exit code 0

除了例中的注解@Service可以实现Bean的IoC以外,Spring还提供了很多其他的注解来实现IoC。

(1)@Component将Java类标记成一个Spring Bean组件。

(2)@Service将业务层实现类标记成一个Spring Bean组件。

(3)@Controller将控制层类标记成一个Spring Bean组件。

(4)@Repository将一个持久层实现类标记成一个Spring Bean组件。

Spring 配置

别名

alias 设置别名 , 为bean设置别名 , 可以设置多个别名

<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="user" alias="userNew"/>

Bean配置

<!--bean就是java对象,由Spring创建和管理-->

<!--
    id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
    如果配置id,又配置了name,那么name是别名
    name可以设置多个别名,可以用逗号,分号,空格隔开
    如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;

    class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
    <property name="name" value="Spring"/>
</bean>

import

团队的合作通过import来实现 .

<import resource="{path}/beans.xml"/>

参考资料

1.Spring 5企业级开发实战/周冠亚,黄文毅著.—北京:清华大学出版社,2019

2.Spring:概述、IOC理论-秦疆-–https://www.bilibili.com/video/av71110355

3.Spring:第一个程序、对象创建方式、配置说明-秦疆。https://www.bilibili.com/video/av71110355

发布了48 篇原创文章 · 获赞 6 · 访问量 6561

猜你喜欢

转载自blog.csdn.net/qq_41569732/article/details/103969494