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

相关文章
|
1月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
9月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
626 26
|
5月前
|
XML 人工智能 Java
Spring IOC 到底是什么?
IOC(控制反转)是一种设计思想,主要用于解耦代码,简化依赖管理。其核心是将对象的创建和管理交给容器处理,而非由程序直接硬编码实现。通过IOC,开发者无需手动new对象,而是由框架负责实例化、装配和管理依赖对象。常见应用如Spring框架中的BeanFactory和ApplicationContext,它们实现了依赖注入和动态管理功能,提升了代码的灵活性与可维护性。
187 1
|
XML Java 数据格式
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
|
6月前
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
|
11月前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
240 69
|
8月前
|
Java 容器 Spring
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
|
11月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
11月前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
178 21
|
11月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
382 12

热门文章

最新文章