Spring-IOC实现【01-XML配置方式】

简介: IOC概念 IoC控制反转(IoC,Inversion of Control), 是一个概念,是一种思想。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。把对象的创建、初始化、 销毁等工作交给spring容器来做。由spring容器控制对象的生命周期。


IOC概念

   IoC控制反转(IoC,Inversion of Control),

   是一个概念,是一种思想。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。把对象的创建、初始化、

   销毁等工作交给spring容器来做。由spring容器控制对象的生命周期。

   DI依赖注入:Dependency Injection。

   依赖注入DI是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。依赖注入是目前最优秀的解耦方式。依赖注入让Spring的Bean之间以配置文件的方式组织在一起,而不是以硬编码的方式耦合在一起的。

   IoC与DI的关系

   IoC是一个概念,是一种思想,其实现方式多种多样。当前比较流行的实现方式之一是DI。

IOC:控制反转, 将 new 的过程交给spring容器去处理

XML配置方式

一、普通构造注入

   创建Spring工程

   创建Spring的XML配置文件applicationContext.xml

image.png

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


   在Spring的配置文件中声明User Bean:

image.png

<?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">
  <!-- 在容器中注册UserBean -->
  <bean class="com.dpb.javabean.UserBean" id="userBean"></bean>
 </beans>

 所谓的声明,就是将自己的信息告诉Spring容器,例如id和class,Spring容器根据class,通过反射(默认使用的是无参构造方法)就可以创建一个名为user1的User对象。

   初始化容器

public static void main(String[] args) {
    //初始化Spring容器,当Spring容器初始化时,会自动加载配置文件,然后根据配置文件中的内容初始化Bean
    ApplicationContext ac = 
        new ClassPathXmlApplicationContext("application.xml");
   }

image.png

5. 初识化Spring容器之后,可以看到User已经被创建出来了。

注意:上面这种初始化方式,要求User必须有一个无参构造方法,如果没有无参构造方法,会抛出如下异常:

image.png

6.通过调用容器中的getBean方法可以获取Spring容器中的对象

public static void main(String[] args) {
    //初始化Spring容器,当Spring容器初始化时,会自动加载配置文件,然后根据配置文件中的内容初始化Bean
    ApplicationContext ac = 
        new ClassPathXmlApplicationContext("application.xml");
    // 去Spring容器中获取一个UserBean对象
    UserBean user = ac.getBean("userBean", UserBean.class);
    System.out.println(user);
  }

image.png

7. 也可以通过类型直接获取一个Bean的实例

image.png

public static void main(String[] args) {
    //初始化Spring容器,当Spring容器初始化时,会自动加载配置文件,然后根据配置文件中的内容初始化Bean
    ApplicationContext ac = 
        new ClassPathXmlApplicationContext("application.xml");
    // 去Spring容器中获取一个UserBean对象 通过类型直接获取
    UserBean user = ac.getBean( UserBean.class);
    System.out.println(user);
  }

这种方式有潜在的隐患:如果Spring容器中有多个User的实例,此时就会报错

image.png

id和name的区别

实际开发过程中我们可以忽略id和name的区别。可以混合使用。通过getBean()方法都可以获取,这个是个重载的方法。

id="user1,user2,user3"
表示bean有一个名字,这个名字就是user1,user2,user3 
name="user1,user2,user3"
表示bean有多个名字,多个名字分别是user1、user2以及user3 

在同一配置文件中ID不要出现重复的。

BeanFactory和ApplicationContext的区别

   /**
   * ApplicationContext 方式加载
   */
  @Test
  public void test1() {
    // 创建容器的同时 容器初始化,容器所有的bean创建完毕
    ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
    // 去Spring容器中获取一个UserBean对象 通过类型直接获取
    UserBean user = ac.getBean(UserBean.class);
    System.out.println(user);
  }
  /**
   * BeanFactory 方式加载
   */
  @Test
  public void test2() {
    // 创建容器对象,BeanFactory当调用getBean获取响应对象是才创建对象
    BeanFactory bf = new XmlBeanFactory(new ClassPathResource("application.xml"));
    // 去Spring容器中获取一个UserBean对象 通过类型直接获取
    UserBean user = bf.getBean(UserBean.class);
    System.out.println(user);
  }

image.png

二、静态工厂注入

创建静态工厂类

/**
 * User 工厂类
 * @author dpb[波波烤鸭]
 *
 */
public class UserFactory {
  /**
   * 必须是static方法
   * @return
   */
  public static UserBean getInstance(){
    return new UserBean();
  }
}

application.xml文件中注册

<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 class="com.dpb.factory.UserFactory" factory-method="getInstance" id="user2"/>
</beans>

获取相应的实例

image.png

应用场景

在一些第三方框架使用过程 中,可能不得不使用静态工厂注入或者实例工厂注入。

image.png

这里以OkHttp为例说明为何需要静态工厂注入

由于OkHttpClient需要通过Builder进行创建,因此无法直接使用构造方法注入。此时可以通过静态工厂注入。

三、动态工厂注入

创建动态工厂类

/**
 * User 工厂类
 * @author dpb[波波烤鸭]
 *
 */
public class UserFactory {
  /**
   * 动态工厂方式获取
   * 普通方法
   * @return
   */
  public  UserBean getInstance(){
    return new UserBean();
  }
}

application.xml注册

<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 -->
  <bean class="com.dpb.factory.UserFactory" id="userFactory"/>
  <!-- 从工厂中获取UserBean对象 -->
  <bean id="user" factory-bean="userFactory" factory-method="getInstance"/>
</beans>

获取实例

image.png

四、属性注入

image.png

构造注入

创建有参构造方法,同时必须提供无参构造方法

image.png

application.xml中注入

<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">
  <!-- 注册UserBean -->
  <bean class="com.dpb.javabean.UserBean" id="userBean">
    <!-- 通过构造注入设置 -->
    <constructor-arg name="id" value="1"/>
    <constructor-arg name="name" value="波波烤鸭"/>
    <constructor-arg name="age" value="18"/>
  </bean>
</beans>

还可以通过下标定位参数

<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">
  <!-- 注册UserBean -->
  <bean class="com.dpb.javabean.UserBean" id="userBean">
    <!-- 通过构造注入设置 通过index 定位设置 -->
    <constructor-arg index="0" value="1"/>
    <constructor-arg index="1" value="波波烤鸭"/>
    <constructor-arg index="2" value="18"/>
  </bean>
</beans>

测试结果

image.png

设值注入

Java对象中提供对应的setter方法

image.png

/**
 * 
 * @author dpb[波波烤鸭]
 *
 */
public class UserBean {
  private int id;
  private String name;
  private int age;
  /**
   * 无参构造方法
   */
  public UserBean() {
    System.out.println("无参构造方法");
  }
  public int getId() {
    return id;
  }
  /**
   * 设值注入 必须提供对应的setter方法
   * @param id
   */
  public void setId(int id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  /**
   * 设值注入 必须提供对应的setter方法
   * @param name
   */
  public void setName(String name) {
    this.name = name;
  }
  public int getAge() {
    return age;
  }
  /**
   * 设值注入 必须提供对应的setter方法
   * @param age
   */
  public void setAge(int age) {
    this.age = age;
  }
  @Override
  public String toString() {
    return "UserBean [id=" + id + ", name=" + name + ", age=" + age + "]";
  }
  public void say(){
    System.out.println("hello ...");
  }
}

application.xml配置

<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">
  <!-- 注册UserBean -->
  <bean class="com.dpb.javabean.UserBean" id="userBean">
    <!--通过设值注入的方式注入  -->
    <property name="id" value="2"/>
    <property name="name" value="bobo烤鸭"/>
    <property name="age" value="32"/>
  </bean>
</beans>

测试

image.png

p名称空间注入

image.png

JavaBean对象

/**
 * p名称空间注入
 * @author dpb[波波烤鸭]
 *
 */
public class Person {
  private int id;
  private String name;
  private String address;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }
  @Override
  public String toString() {
    return "Person [id=" + id + ", name=" + name + ", address=" + address + "]";
  }
}

application.xml配置

image.png

<!-- 注册 Person -->
<bean id="person" class="com.dpb.javabean.Person" p:id="3" p:name="邓澎波" p:address="深圳"/>

测试

image.png

image.png

对象注入

对象可以通过构造方法、set方法或者p名称空间注入,步骤如下:

Student类和Cat类

/**
 * 学生
 * @author dpb[波波烤鸭]
 *
 */
public class Student {
  private int id;
  private String name;
  // 拥有的 cat
  private Cat cat;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Cat getCat() {
    return cat;
  }
  public void setCat(Cat cat) {
    this.cat = cat;
  }
  @Override
  public String toString() {
    return "Student [id=" + id + ", name=" + name + ", cat=" + cat + "]";
  }
}
/**
 * 猫
 * @author dpb[波波烤鸭]
 *
 */
public class Cat {
  private int id;
  private String color;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getColor() {
    return color;
  }
  public void setColor(String color) {
    this.color = color;
  }
  @Override
  public String toString() {
    return "Cat [id=" + id + ", color=" + color + "]";
  }
}

application.xml配置

  <!-- 配置 cat -->
  <bean id="catId" class="com.dpb.javabean.Cat">
    <property name="id" value="1"/>
    <property name="color" value="red"></property>
  </bean>
  <!-- 配置 student对象 -->
  <bean class="com.dpb.javabean.Student">
    <property name="id" value="10"/>
    <property name="name" value="波波烤鸭"/>
    <!-- 对象注入 -->
    <property name="cat" ref="catId"></property>
  </bean>

测试

image.png

数组和集合注入

数组和集合的注入方式是一致的,无论是基本数据类型还是一个引用,注入方式都是一样。 首先声明一个对象,对象中包含集合和数组

对象中添加对应的类型数据image.pngimage.png

application.xml注入

<!-- 配置 student对象 -->
  <bean class="com.dpb.javabean.Student">
    <property name="id" value="10"/>
    <property name="name" value="波波烤鸭"/>
    <!-- 对象注入 -->
    <property name="cat" ref="catId"></property>
    <!-- List集合注入 -->
    <property name="games">
      <list>
        <value>LOL</value>
        <value>DNF</value>
        <value>CS</value>
      </list>
    </property>
    <!-- 数组注入 -->
    <property name="books">
      <list>
        <bean class="com.dpb.javabean.Book">
          <property name="id" value="1001"/>
          <property name="bookName" value="西游记"/>
        </bean>
        <bean class="com.dpb.javabean.Book">
          <property name="id" value="1002"/>
          <property name="bookName" value="红楼梦"/>
        </bean>
      </list>
    </property>
  </bean>

测试

image.png

Map注入

声明Map属性,注意属性的key和value的数据类型需要提前定义好,然后在xml文件中直接使用(xml文件中配置时,key和属性的值必须要满足声明的要求,否则就会出错)。

对象中添加 Map属性

image.png

配置文件注入

<property name="score">
  <map>
    <entry key="数学" value="99"/>
    <entry key="英语" value="78"/>
    <entry key="化学" value="84"/>
  </map>
</property>

测试

image.png

props注入

properties注入与map注入类似

对象中添加properties属性

image.png

配置文件中注入

<property name="props">
  <props>
    <prop key="userName">admin</prop>
    <prop key="password">123</prop>
  </props>
</property>

测试

image.png


相关文章
|
3月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
3月前
|
Java 关系型数据库 MySQL
Spring Boot自动配置:魔法背后的秘密
Spring Boot 自动配置揭秘:只需简单配置即可启动项目,背后依赖“约定大于配置”与条件化装配。核心在于 `@EnableAutoConfiguration` 注解与 `@Conditional` 系列条件判断,通过 `spring.factories` 或 `AutoConfiguration.imports` 加载配置类,实现按需自动装配 Bean。
|
3月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
1385 0
|
5月前
|
Java Spring
Spring Boot配置的优先级?
在Spring Boot项目中,配置可通过配置文件和外部配置实现。支持的配置文件包括application.properties、application.yml和application.yaml,优先级依次降低。外部配置常用方式有Java系统属性(如-Dserver.port=9001)和命令行参数(如--server.port=10010),其中命令行参数优先级高于系统属性。整体优先级顺序为:命令行参数 &gt; Java系统属性 &gt; application.properties &gt; application.yml &gt; application.yaml。
1000 0
|
2月前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
2月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
3月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
625 5
|
8月前
|
安全 Java API
深入解析 Spring Security 配置中的 CSRF 启用与 requestMatchers 报错问题
本文深入解析了Spring Security配置中CSRF启用与`requestMatchers`报错的常见问题。针对CSRF,指出默认已启用,无需调用`enable()`,只需移除`disable()`即可恢复。对于`requestMatchers`多路径匹配报错,分析了Spring Security 6.x中方法签名的变化,并提供了三种解决方案:分次调用、自定义匹配器及降级使用`antMatchers()`。最后提醒开发者关注版本兼容性,确保升级平稳过渡。
992 2
|
3月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
203 0
探索Spring Boot的@Conditional注解的上下文配置
|
9月前
|
缓存 Java API
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
本文介绍了在Spring Boot中配置Swagger2的方法。通过创建一个配置类,添加`@Configuration`和`@EnableSwagger2`注解,使用Docket对象定义API文档的详细信息,包括标题、描述、版本和包路径等。配置完成后,访问`localhost:8080/swagger-ui.html`即可查看接口文档。文中还提示了可能因浏览器缓存导致的问题及解决方法。
1060 0
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置