Spring 6(二)【IOC(3)

简介: Spring 6(二)【IOC

Spring 6(二)【IOC(2)https://developer.aliyun.com/article/1532217

1.11、基于 XML 的自动装配

所谓自动装配其实就是为了减少我们配置 Spring 配置文件的工作量,比较一个 JavaBean 如果有很多属性的话,我们自己一个一个去配置添加属性太复杂了,所以就有了自动装配这个概念。

自动装配有两种方式:通过属性类型来自动装配(byType),通过属性名来自动装配(byName)。

  • byType:根据类型匹配IOC容器中的某个兼容类型的bean,为属性自动赋值
  • 如果在IOC中,没有任何一个兼容类型的bean能够为属性赋值,则该属性不装配,即值为默认值 null
  • 如果在IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException
  • byName:将自动装配的属性的属性名,作为bean的id在IOC容器中匹配相对应的bean进行赋值

这里我们写一个测试模拟我们开发的一个的场景,controller 负责响应通过 service 来实现,service 会调用 dao 层来实现持久化。

(1)编写 Service 层代码:

package com.lyh.study.service;
 
public interface UserService {
    void addUser();
}
package com.lyh.study.service;
 
import com.lyh.study.dao.UserDao;
 
public class UserServiceImpl implements UserService {
 
    private UserDao userDao;
 
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
 
    @Override
    public void addUser() {
        System.out.println("addUser() 方法执行");
        userDao.addUser();
    }
}

(2)编写 Dao 层代码 :

package com.lyh.study.dao;
 
public interface UserDao {
    void addUser();
}
package com.lyh.study.dao;
 
public class UserDaoImpl implements UserDao{
 
    @Override
    public void addUser() {
        System.out.println("添加成功");
    }
}

(3)编写 controller 层代码:

package com.lyh.study.controller;
 
import com.lyh.study.service.UserService;
 
public class UserController {
 
    private UserService userService;
 
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
 
    public void addUser(){
        userService.addUser();
    }
 
}

1.11.1、byType 自动装配

<bean id="userController" class="com.lyh.study.controller.UserController" autowire="byType"/>
    <bean id="userService" class="com.lyh.study.service.UserServiceImpl" autowire="byType"/>
    <bean id="userDao" class="com.lyh.study.dao.UserDaoImpl"/>

1.11.2、byName 自动装配

<bean id="userController" class="com.lyh.study.controller.UserController" autowire="byName"/>
    <bean id="userService" class="com.lyh.study.service.UserServiceImpl" autowire="byName"/>
    <bean id="userDao" class="com.lyh.study.dao.UserDaoImpl"/>

测试:

    @Test
    public void testAutoWireByType(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        UserController userController = ac.getBean(UserController.class);
        userController.addUser();
    }

运行结果:

addUser() 方法执行
添加成功

2、基于注解管理 Bean

除了上面的直接手动配置 Spring 配置文件以外,我们实际用的更多应该就是使用注解注入了。

2.1、开启扫描组件

       Spring 默认不使用注解装配 Bean,因此我们需要在 Spring 的 XML 配置中,通过 context:component-scan 元素开启 Spring Beans的自动扫描功能。开启此功能后,Spring 会自动从扫描指定的包(base-package 属性设置)及其子包下的所有类,如果类上使用了 @Component 注解,就将该类装配到容器中。

也就是在 Spring 配置文件中加这么一行:

<context:component-scan base-package="com.lyh.study"/>

注意:在使用 context:component-scan 元素开启自动扫描功能前,首先需要在 XML 配置的一级标签  中添加 context 相关的约束。

2.1.1、默认扫描方式

<context:component-scan base-package="com.lyh.study"/>

也就是我们上面演示的,它会扫描 com.lyh.study 包下所有被 @Component 注解标注的类并帮我们注册到 IOC 容器中管理。

2.1.2、指定要排除的组件

标签

<!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <context:component-scan base-package="com.lyh.study" use-default-filters="false">
        <!--
    type:设置包含的依据
    type="annotation",根据注解排除,expression中设置要排除的注解的全类名
    type="assignable",根据类型排除,expression中设置要排除的类型的全类名
      -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="assignable" expression="com.lyh.study.controller.UserController"/>
    </context:component-scan>

2.1.3、仅扫描指定组件

标签

<!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <context:component-scan base-package="com.lyh.study" use-default-filters="false">
        <!--
    type:设置排除的依据
    type="annotation",根据注解排除,expression中设置要排除的注解的全类名
    type="assignable",根据类型排除,expression中设置要排除的类型的全类名
      -->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:include-filter type="assignable" expression="com.lyh.study.controller.UserController"/>
    </context:component-scan>

2.2、使用注解定义 Bean

Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean。

注解 说明
@Component 该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。
@Repository 该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller 该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

2.3、@Autowired 注入

单独使用 @Autowired注解时,默认根据类型装配(byType)

2.3.1、属性注入

上面 2.1 中我们的 UserController 中有一个属性是 UserService 类型的对象,而 UserService 这个类当中也有一个类型为 UserDao 的属性;所以我们当时必须提供 setter 方法,因为它是是通过 setter 方法进行注入的;但是现在使用注解开发我们就可以省去 setter 方法:

package com.lyh.study.service;
 
import com.lyh.study.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
@Service
public class UserServiceImpl implements UserService {
 
    @Autowired
    private UserDao userDao;
 
    @Override
    public void addUser() {
        System.out.println("addUser() 方法执行");
        userDao.addUser();
    }
}
import org.springframework.stereotype.Repository;
 
@Repository
public class UserDaoImpl implements UserDao{
 
    @Override
    public void addUser() {
        System.out.println("添加成功");
    }
}
package com.lyh.study.controller;
 
import com.lyh.study.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
 
@Controller
public class UserController {
 
    @Autowired
    private UserService userService;
 
    public void addUser(){
        userService.addUser();
    }
 
}

这次我们使用了注解 @Service、Repository、Controller 分别标注了我们的 UserController、UserDao 和 UserController ,而且即使它们的 Bean 中包含了一些属性,我们并没有提供 setter 方法,因为使用注解开发时,不需要给 Bean 提供 setter 方法

测试:

    @Test
    public void testAutoWireByType(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        UserController userController = ac.getBean("userController",UserController.class);
        userController.addUser();
    }

运行结果:

addUser() 方法执行
添加成功

2.3.2、set 注入

上面的属性注入中,我们把 @Autowired 这个注解标注在了属性上,这种方式不需要我们实现属性的 setter 方法;而 set 注入是直接把 @Autowired 这个注解标注在方法上:

package com.lyh.study.controller;
 
import com.lyh.study.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
 
@Controller
public class UserController {
    
    private UserService userService;
 
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
 
    public void addUser(){
        userService.addUser();
    }
 
}
package com.lyh.study.service;
 
import com.lyh.study.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
@Service
public class UserServiceImpl implements UserService {
    
    private UserDao userDao;
 
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
 
    @Override
    public void addUser() {
        System.out.println("addUser() 方法执行");
        userDao.addUser();
    }
}

这里不再测试运行结果了,效果和属性注入是一样的。个人推荐这种方式,尽量养成一个给属性添加 setter 方法的好习惯,而且属性注入 Idea 会给一个警告提示,虽然也用起来没问题,但是强迫症实在受不了。

Spring 6(二)【IOC(4)https://developer.aliyun.com/article/1532221

相关文章
|
7月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
487 26
|
4月前
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
|
9月前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
187 69
|
6月前
|
Java 容器 Spring
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
|
9月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
9月前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
139 21
|
9月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
216 12
|
9月前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
202 2
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
610 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
11月前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
694 1
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码