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

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 【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


注入成功。

相关文章
|
3天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
3天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
39 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
4天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
4天前
|
Java 数据库连接 Maven
Spring基础1——Spring(配置开发版),IOC和DI
spring介绍、入门案例、控制反转IOC、IOC容器、Bean、依赖注入DI
Spring基础1——Spring(配置开发版),IOC和DI
|
19天前
|
监控 安全 Java
【开发者必备】Spring Boot中自定义注解与处理器的神奇魔力:一键解锁代码新高度!
【8月更文挑战第29天】本文介绍如何在Spring Boot中利用自定义注解与处理器增强应用功能。通过定义如`@CustomProcessor`注解并结合`BeanPostProcessor`实现特定逻辑处理,如业务逻辑封装、配置管理及元数据分析等,从而提升代码整洁度与可维护性。文章详细展示了从注解定义、处理器编写到实际应用的具体步骤,并提供了实战案例,帮助开发者更好地理解和运用这一强大特性,以实现代码的高效组织与优化。
30 0
|
Java Spring 容器
Spring 源码解析 | populateBean 属性填充(上)
本文主要是讲 Spring 容器的启动过程主要是以题干的方式进行可能不回涉及过多的细节,希望大家阅读本文能对 Spring 源码有一个简单的了解。 环境介绍: Spring 5.3.10 Jdk 11
209 0
Spring 源码解析 | populateBean 属性填充(上)
|
Java Spring 容器
Spring 源码解析 | populateBean 属性填充(下)
本文主要是讲 Spring 容器的启动过程主要是以题干的方式进行可能不回涉及过多的细节,希望大家阅读本文能对 Spring 源码有一个简单的了解。 环境介绍: Spring 5.3.10 Jdk 11
167 0
|
Java 数据库连接 Spring
Spring 属性填充(下)
Spring 的属性填充主要是在 Bean 被创建后,通过 populateBean 方法来完成对象属性赋值以逐步完成 Bean 的初始化工作。
180 0
|
Java Spring
Spring 属性填充(上)
Spring 的属性填充主要是在 Bean 被创建后,通过 populateBean 方法来完成对象属性赋值以逐步完成 Bean 的初始化工作。
142 0