【Spring 从0开始】IOC容器的Bean管理 - 基于注解 - 属性注入

简介: 【Spring 从0开始】IOC容器的Bean管理 - 基于注解 - 属性注入

基于注解方式进行属性注入,涉及到 4 个注解:


  • @Autowired:根据属性类型,进行自动装配
  • @Qualifier:根据属性名称进行注入,跟 @Autowired 一起使用
  • @Resource:既可以根据类型注入,也可以根据名称注入
  • @Value:注入普通类型属性


一、@Autowired


现在有这样的一个结构,我要在 service 里注入 dao 对象。


1268169-20210801102821199-2118216264.png


1. 添加对象注解


给 service 和 dao 添加注解,用来创建对象。


为了区分明显,service 层用 @Service,dao 层用 @Repository。


// content of UserService
@Service
public class UserService {
    public void add() {
        System.out.println("service add() ... ...");
    }
}
@Repository
public class UserDaoImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("UserDao add()... ...");
    }
}


2. 在service中注入dao对象


@Service
public class UserService {
    // 定义 dao 属性
    @Autowired
    private UserDao userDao;
    public void add() {
        System.out.println("service add() ... ...");
        userDao.add();
    }
}


先定义 dao 属性,然后在上面添加注解 @Autowired 即可,而且不需要我们手动添加 set 方法了。


为了方便看到注入成功效果,里面还调用了 userDao.add() 方法。


3. 创建测试函数测试效果


public class TestService {
    @Test
    public void testService() {
        ApplicationContext context
                = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}


这里调用了 userService.add() 方法,而 userService.add() 内部又调用了 userDao.add(),所以应该可以看到 2 个输出:


com.pingguo.spring5.service.UserService@23f7d05d
service add() ... ...
UserDao add()... ...
Process finished with exit code 0


二、@Qualifier


根据属性名称进行注入,跟 @Autowired 一起使用。


为什么要一起使用?


比如现在,我新增一个 dao 的实现类 UserDaoImpl2


1268169-20210801105507406-835788585.png


@Repository
public class UserDaoImpl2 implements UserDao {
    @Override
    public void add() {
        System.out.println("UserDao UserDaoImpl2 add()... ...");
    }
}


所以现在 UserDaoImpl 和 UserDaoImpl2 这2个类都是同一种类型,那么 @Autowired 注入的时候到底是用哪个类呢?于是报错了。


1268169-20210801105729370-1791421364.png


所以,要加上 @Qualifier 来指定其中一个的具体名称。比如,我这里使用 UserDaoImpl2 。


1268169-20210801105850313-1866980572.png


再次执行测试函数:


com.pingguo.spring5.service.UserService@75f32542
service add() ... ...
UserDao UserDaoImpl2 add()... ...
Process finished with exit code 0


可以看到 UserDaoImpl2 里的内容被输出,注入正确。


三、@Resource


既可以根据类型注入,也可以根据名称注入。


1. 替代 @Autowired


可以直接替代 @Autowired 使用。


现在我把 UserDaoImpl2 这个实现类注释掉,只留下一个实现类。


service 里使用 @Resource 注解:


@Service
public class UserService {
    // 定义 dao 属性
    @Resource
    private UserDao userDao;
    public void add() {
        System.out.println("service add() ... ...");
        userDao.add();
    }
}


运行测试:


com.pingguo.spring5.service.UserService@23f7d05d
service add() ... ...
UserDao add()... ...
Process finished with exit code 0


结果正确。


2. 替换 @Qualifier


替换 @Qualifier 使用的话,里面的值用 name 传递,比如 @Resource(name = "userDaoImpl2")


现在去掉 UserDaoImpl2 的注释,让 dao 有 2 个实现类。


service 中 使用 @Resource 注解:


@Service
public class UserService {
    // 定义 dao 属性
    @Resource(name = "userDaoImpl2")
    private UserDao userDao;
    public void add() {
        System.out.println("service add() ... ...");
        userDao.add();
    }
}


运行测试:


com.pingguo.spring5.service.UserService@197d671
service add() ... ...
UserDao UserDaoImpl2 add()... ...
Process finished with exit code 0


结果正确。


这里要提一下的是,Resource 是来自拓展包 javax。另外 2个 则是来自官方框架包,优先使用。


1268169-20210801142531801-1720310817.png


四、@Value


上面使用的都是注入对象类型的属性,使用 @Value 可以注入普通类型,比如 String。

在 service 里增加一个 String 类型的属性 userName,并且在下面的方法里做个打印输出。


@Service
public class UserService {
    // 定义 dao 属性
    @Autowired
    @Qualifier(value = "userDaoImpl2")
    private UserDao userDao;
    @Value(value = "spring 从0开始")
    private String userName;
    public void add() {
        System.out.println("service add() ... ...");
        System.out.println(userName);
        userDao.add();
    }
}


运行测试:


com.pingguo.spring5.service.UserService@184cf7cf
service add() ... ...
spring 从0开始
UserDao UserDaoImpl2 add()... ...
Process finished with exit code 0


注入成功。

相关文章
|
5月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
904 26
|
10月前
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
270 18
|
XML Java 数据格式
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
231 21
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
543 12
|
前端开发 Java Docker
使用Docker容器化部署Spring Boot应用程序
使用Docker容器化部署Spring Boot应用程序
|
Java Docker 微服务
利用Docker容器化部署Spring Boot应用
利用Docker容器化部署Spring Boot应用
338 0
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
309 0
|
Java Spring 容器
Spring 源码解析 | populateBean 属性填充(上)
本文主要是讲 Spring 容器的启动过程主要是以题干的方式进行可能不回涉及过多的细节,希望大家阅读本文能对 Spring 源码有一个简单的了解。 环境介绍: Spring 5.3.10 Jdk 11
419 0
Spring 源码解析 | populateBean 属性填充(上)