程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-05(1)

Spring IOC的简单介绍

发布于2021-06-12 15:35     阅读(701)     评论(0)     点赞(24)     收藏(1)


Spring IOC


什么是IOC

IOC是Inversion of Control的缩写,直译为控制反转。简单的说就是当我们需要一个对象时,不再由我们自己手动去创建,而是让框架代替我们去创建,把控制权交给框架,也就是控制反转。

IOC又可以叫DI(Dependency Injection),直译为依赖注入。将我们需要依赖的的对象由框架自动注入。

引入IOC最主要的目的就是为了实现对象间的解耦。

参考网址:https://www.cnblogs.com/DebugLZQ/archive/2013/06/05/3107957.html


什么是Bean

在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IOC容器实例化、组装和管理的对象。

虽说bean在Spring中指的是对象,但JavaBean却是一种类,两者非常容易混淆,所以我通常还是习惯于将由IoC容器管理的对象的类称为bean

参考网址:https://www.cnblogs.com/wwct/p/12742347.html


第一个Spring程序

  1. 新建一个maven项目

  2. 导入spring-context依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.8.RELEASE</version>
    </dependency>
    
  3. 新建一个UserService类,内容如下

    public class UserService {
        public void test(){
            System.out.println("我是userService的test方法");
        }
    }
    
  4. 新建一个配置文件夹resources,并在里面新建一个配置文件spring.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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <!--
      定义bean对象
      id:     bean对象的唯一标识
      class:  bean对象对应的全路径
      -->
      <bean id="userService" class="org.example.UserService"></bean>
      <!-- more bean definitions go here -->
    </beans>
    
  5. 新建一个启动类starter,内容如下:

    public class Starter {
    
        public static void main(String[] args) {
            // 创建Spring的上下文环境(Spring IOC 容器),并负责实例化,配置和组装Bean
            ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
            // 创建bean,传入bean的id
            UserService userService = (UserService) ac.getBean("userService");
    
            userService.test();
        }
    }
    
    
  6. 运行程序,可以查看到控制台输出我是userService的test方法

通过这个简单的示例程序,我们可以看到,我们没有new一个UserService对象,但却拿到该对象,说明这个对象是由spring帮我们实例化的,这就是IOC。


加载配置文件

主要有两种方式,一种通过相对路径,一种通过绝对路径,但一般我们都使用相对路径。这两种方式都支持一次性写入多个配置文件。

  1. 相对路径:

    ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");// 单个
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring01.xml", "spring02.xml");// 多个
    
  2. 绝对路径:

    ApplicationContext ac = new FileSystemXmlApplicationContext("C:/.../.../src/main/resources/spring.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

  <!-- 导入配置文件 -->
  <import resource="spring01.xml"/>
  <import resource="spring02.xml"/>

</beans>

Bean的实例化

  1. 构造器实例化:就是我们上面的例子中的,默认是通过无参构造器进行实例化,比较常用,例如:

    <bean id="userService" class="org.example.UserService"/>
    
  2. 静态工厂实例化:通过工厂方法进行实例化,需要先写一个静态工厂,并配置factory-method,例如:

    public class MyFactory {
        /*定义对应的工厂方法,返回实例化对象*/
        public static UserService createUserService(){
            return new UserService();
        }
    }
    
    <!--
    静态工厂实例化
    class:          指定静态工厂类
    factory-method: 对应的实例化方法
    -->
    <bean id="userService" class="org.example.MyFactory" factory-method="createUserService"/>
    
  3. 实例化工厂实例化:工厂方法为非静态的,且需要先将实例化工厂实例化为bean,并配置factory-methodfactory-bean,例如:

    public class MyFactory {
        /*定义对应的工厂方法,返回实例化对象*/
        public UserService createUserService(){
            return new UserService();
        }
    }
    
    <bean id="myFactory" class="org.example.MyFactory"/>
    <bean id="userService" factory-bean="myFactory" factory-method="createUserService"/>
    

手动注入(手动装配)

即通过配置文件进行依赖注入,常用的set方法注入,构造器注入两种。首先我们定义一个UserDAO,其被UserService依赖,如下

public class UserDAO {
    public void test(){
        System.out.println("我是UserDAO的test");
    }
}

set方法注入

这种方法需要提供依赖的set方法,例如

public class UserService {

    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    private UserDAO userDAO;

    public void test(){
        System.out.println("我是userService的test方法");
        userDAO.test();
    }

}

配置文件通过需要property标签,对依赖进行手动注入,例如

<!-- 依赖的bean定义 -->
<bean id="userDAO" class="org.example.UserDAO"/>
<!-- 通过set方法,手动注入依赖 -->
<bean id="userService" class="org.example.UserService">
	<!--  name:属性名,ref:对应的bean  -->
	<property name="userDAO" ref="userDAO"/>
</bean>

若需要注入intString等类型的依赖,可以将ref属性换成value属性,其他一样。

构造器注入

需要提供对应的带参构造器,例如

public class UserService {

    private UserDAO userDAO;

    public UserService(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    public void test(){
        System.out.println("我是userService的test方法");
        userDAO.test();
    }

}
<!-- 依赖的bean定义 -->
<bean id="userDAO" class="org.example.UserDAO"/>
<!-- 通过set方法,手动装配依赖 -->
<bean id="userService" class="org.example.UserService">
	<!--name:构造器中的参数名,ref:对应的bean  -->
	<constructor-arg name="userDAO" ref="userDAO"/>
</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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- 开启自动装配 -->
  <context:annotation-config/>

  <bean id="userDAO" class="org.example.UserDAO"/>
  <bean id="userService" class="org.example.UserService"/>
</beans>

实现自动注入主要有两个注解:ResourceAutowired,将他们注解在需要注入的bean上即可,也可以注解在bean的set方法上。

Resource

  1. 默认会根据bean的id查找,属性名最好与bean标签id属性值相等
  2. 如果根据id未找到,则会根据类型(Class)查找
  3. 可以设置注解的name属性,name属性值必须与bean标签的id属性值保持一致
  4. 如果注入的是接口,且有多个实现类,则需要使用name属性指定id
public class UserService {

    // @Resource(name = "userDAO")
    @Resource
    private UserDAO userDAO;

    public void test(){
        System.out.println("我是userService的test方法");
        userDAO.test();
    }

}

Autowired

  1. 默认通过类型(Class类型)查找bean对象,与属性字段的名称无关
  2. 可以与Qualifie注解结合使用,通过value属性值查找bean对象,value属性值必须要设置,且值要与bean标签的id属性值对应
public class UserService {

    @Autowired
    @Qualifier(value = "userDAO")
    private UserDAO userDAO;

    public void test(){
        System.out.println("我是userService的test方法");
        userDAO.test();
    }

}

扫描器

实际的开发中,bean的数量非常多,采用手动配置bean的方式已无法满足生产需要,Spring这时候同样提供了扫描的方式,对扫描到的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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- 开启自动装配 -->
  <context:annotation-config/>
  <!-- 开启扫描器 -->
  <context:component-scan base-package="org.example"/>
</beans>

然后,我们只需要在包中的类前加上对应的注解,即可自动扫描进容器,主要有以下四个注解

  1. Repository:用于DAO层
  2. Service:用于服务层
  3. Controller:用于控制层
  4. Component:用于任意类,如工具类等
@Repository
public class UserDAO {
    public void test(){
        System.out.println("我是UserDAO的test");
    }
}

Bean的作用域

主要分别为两种,单例作用域和原型作用域,默认是单例作用域。

  1. 单例(singleton)作用域:

    其中,lazy-init是懒加载,当lazy-inittrue时,当程序调用时才会去实例化该bean对象,默认为false

    所有的bean对象都是单例,因为是默认配置,所以不需要写啥。

  2. 原型(prototype)作用域:当每次使用时,都会创建一个新的bean对象,不会缓存。需要配置scope="prototype",例如

    <bean id="userService" class="org.example.UserService" scope="prototype"/>
    

Bean的生命周期

主要分为四个阶段:

  1. 定义:在配置文件中定义bean标签,设置对应的id等属性

  2. 创建:在Spring容器中,默认在启动时就会创建所有的bean对象,除非lazy-init="true"。若在创建时需要执行一些操作,可以在bean标签中设置init-method为初始化函数,例如:

    <bean id="userService" class="org.example.UserService" init-method="init"/>
    
  3. 使用:使用getBean获取bean对象进行使用

  4. 销毁:在bean中设置destroy-method为销毁函数,并通过AbstractApplicationContext对象,调用其close方法销毁bean(若不使用close方法,在项目结束时也不会销毁bean),例如

    <bean id="userService" class="org.example.UserService" destroy-method="destroy"/>
    
    // 创建Spring的上下文环境(Spring IOC 容器),并负责实例化,配置和组装Bean
    AbstractApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
    // 创建bean对象,传入bean对象的id
    UserService userService = (UserService) ac.getBean("userService");
    
    userService.test();
    // 销毁bean对象
    ac.close();
    


所属网站分类: 技术文章 > 博客

作者:小胖子爱java

链接:http://www.javaheidong.com/blog/article/222553/5cc1b71e3558f01df96a/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

24 0
收藏该文
已收藏

评论内容:(最多支持255个字符)