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

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 【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—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
356 26
|
7月前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
157 12
|
7月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
158 12
|
7月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
158 6
|
7月前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
363 4
|
7月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
108 1
|
1月前
|
Prometheus 监控 Cloud Native
Spring Boot 可视化监控
本文介绍了如何通过Spring Actuator、Micrometer、Prometheus和Grafana为Spring Boot应用程序添加监控功能。首先创建了一个Spring Boot应用,并配置了Spring Actuator以暴露健康状态和指标接口。接着,利用Micrometer收集应用性能数据,并通过Prometheus抓取这些数据进行存储。最后,使用Grafana将Prometheus中的数据可视化,展示在精美的仪表板上。整个过程简单易行,为Spring Boot应用提供了基本的监控能力,同时也为后续扩展更详细的监控指标奠定了基础。
132 2
|
4月前
|
Java Spring
SpringBoot自动配置原理
本文深入解析了SpringBoot的核心功能——自动配置,重点探讨了`org.springframework.boot.autoconfigure`及相关注解的工作机制。通过分析`@SpringBootApplication`、`@EnableAutoConfiguration`等注解,揭示了SpringBoot如何基于类路径和条件自动装配Bean
151 7
|
4月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
98 0
|
4月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
123 0