锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 软件开发
  3. 更简单的存取Bean方式-@Bean方法注解

更简单的存取Bean方式-@Bean方法注解

0
  • 软件开发
  • 发布于 2024-09-11
  • 0 次阅读
黄健
黄健

1.@Bean方法存储

类注解是添加在某个类上的,那么方法注解是添加在某个方法前的

public class UserBeans {
    @Bean
    public User user1(){
        User user = new User();
        user.setUid(001);
        user.setUname("zhangsan");
        user.setAge(19);
        user.setPassword("123123");
        return user;
    }

}

当我们使用测试类去获取Bean时,发现获取不到

图一

无法正确拿到Bean的原因:

原因一:@Bean命名规则和不打雷注解的命名规则不同,@Bean存储的对象的命名默认是方法的名称

此时改动对象名称为user1(方法名),发现还是会报错

原因二:方法注解是要配合五大类注解使用

注意:无法获取到对象的原因有两个,名称必须是方法名且方法注解需要配合五大类注解

名称不能换成类名, 对象名等,加上五大类注解也不能成功获取到!!

这是spring的规定,这么做也是为了整体性能的提升,只扫描加了五大类注解的类下是否有@Bean方法注解,没有五大类注解,就不扫描该类是否有方法注解

我们看一些其他场景,一般方法名都是带动词的,get,set等等,但是对象名称是一个名词,所以直接将方法名称写进去是不太合适的.Bean名称是可以改动的,给注解设置参数即可

通过观察Bean源码发现@Bean(name = " “)和@Bean(value = " “)都可以进行设置Bean名称

还可以设置多个名称

@Bean(name = {"user","u1"})

那么设置了重命名之后,还能使用原方法名获取对象的方式还能使用吗?

答案是不能的,重命名之后默认方法名获取的方式就不能获取到Bean了

如果同一个类中有多个方法返回user呢,是否能拿到重命名后的bean?

package com.java.demo.component;

import com.java.demo.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class UserBeans {
    @Bean(name = {"user","u1"})
    public User user1(){
        User user = new User();
        user.setUid(001);
        user.setUname("zhangsan");
        user.setAge(19);
        user.setPassword("123123");
        return user;
    }

    @Bean
    public User user2(){
        User user = new User();
        user.setUid(002);
        user.setUname("Lisi");
        user.setAge(29);
        user.setPassword("321123");
        return user;
    }

}

是可以的,spring是允许将同一个类型的多个对象存储到容器中的

如果两个类中有相同的方法名,返回相同的user时,会出现什么情况呢?

执行多次,结果都是相同的,是因为类似于hashmap中的覆盖,zhangsan先注入,wangwu后注入,加载出来的对象就是wangwu

可使用@Order控制诸如顺序,值越小,优先级越高,越先注入,被覆盖的可能就会增大

让wangwu先注入.lisi后注入,再获取username

此时获取的是lisi这个bean

注入的方法是不能带有参数的,因为容器加载启动的时候,就会将Bean存储到容器中,而你是没有办法给传参的

2.获取Bean对象

获取Bean对象也叫做对象装配,是把对象取出来放到某个类中,也叫对象装配

实现方法有三种:

1.属性注入(Field Injection)

是日常开发使用最多的注入方式

优点是使用简单,只需要给变量添加一个注解(@Autowired)就可以在不new对象的情况下,直接获得注入的对象

注意:在静态方法中不能使用这个注解,因为静态模块是在spring加载之前就加载了的,根本获取不到

我们在controller中获取service的Bean 并使用

获取成功

缺点:

1.无法注入不可变对象

2.只适用于IoC容器,兼容性不好

3.可能违反单一设计原则

2.setter注入(Setter Injection)

优点:符合单一设计原则,每次传输的都是单个变量

缺点:

1.不能注入不可变对象

2.使用setter注入的对象可能被修改,普通的set方法支持可能被调用多次,每次可以传输不同的对象

3.构造方法注入(Spring官方推荐的注入方式)

 private final UserService service;
    @Autowired
    public UserController(UserService service) {
        this.service = service;
    }

    public void sayHi(){
        System.out.println("com.java.demo --do userController sayHi()");
        service.sayHi();
    }

注意:如果当只有一个构造方法时,spring允许不加@Autowired注解!前两种方式不能进行省略,会报异常!

优点:

1.能注入不可变对象(使用final修饰的对象)

为啥属性注入,setter注入不可以呢?被final修饰的对象必须满足二者之一的条件,要么直接创建时进行赋值,要么在构造器中赋值!

2.注入的对象不会被改变,构造方法只能执行一次

3.保障注入对象完全被初始化

4.兼容性更好

还有另一个注解关键字@Resource

@Resource与@Autowired的区别

1.@Resource来自jdk,@Autowired来自Spring

2.使用时设置的参数不同,@Resource可以支持更多的参数设置

@Autowired则没有,当同一个类型的类被注入多个到spring,就需要设置一些内部属性

下文有示例,使用@Resource设置参数

3.@Resource不能用于构造方法注入

区别4:

在spring容器中找Bean,有两种方式 1.根据类型查找 2.根据名称查找

@Component
@Order(20)
public class UserBeans2 {
    @Bean(name = {"user1","u1"})
    public User user1(){
        User user = new User();
        user.setUid(001);
        user.setUname("zhangsan");
        user.setAge(19);
        user.setPassword("123123");
        return user;
    }

    @Bean
    public User user2(){
        User user = new User();
        user.setUid(002);
        user.setUname("wangwu");
        user.setAge(29);
        user.setPassword("321123");
        return user;
    }

}


@Component
@Order(30)
public class UserBeans {
    @Bean
    public User user3(){
        User user = new User();
        user.setUid(002);
        user.setUname("Lisi");
        user.setAge(29);
        user.setPassword("321123");
        return user;
    }

}

@Autowired先根据类型查找,如果类型比较多,再根据名称查找,如果还没找到唯一的Bean,就报错

Caused by: org.springframework.beans.factory.
NoUniqueBeanDefinitionException: 
No qualifying bean of type 'com.java.demo.entity.User' available: 
expected single matching bean but found 2: user1,user2,user3

这里由于注入了相同类型的Bean(User),所以@Autowired还要根据名称查找,但是名称有三个,不能唯一确定,就报错了

将Controller2中的名称修改后,就能找到唯一确定的Bean

user1对应的name是zhangsan

成功找到

如果改动名字影响很大,不能改变.@Resource也解决不了,它是先根据名称查,再根据类型查找

这就是@Resource和@Autowired的第四个区别


不想改变名称,但是我们@Resource可以设置参数!!!

使用@Resource设置一个新的名称

成功拿到

@Autowired是设置不了的!

如果不使用@Reousrce.可使用@Autowired和@Qualifier同时完成获取Bean

成功获取到了

关于更加简单的存取Bean内容就结束了

原文链接: https://blog.csdn.net/chenchenchencl/article/details/130184102

标签: #Spring 84 #软件开发 1171 #JAVA 991
相关文章

万字:支付“核心系统”详解 2024-11-02 15:33

专栏作者:隐墨星辰 \| 主编:陈天宇宙 这篇文章也尝试化繁为简,探寻支付系统的本质,讲清楚在线支付系统最核心的一些概念和设计理念。 虽然支付行业已经过了风头最劲的时光,但跨境支付仍然在蓬勃发展,每年依然有很多新人进入这个行业,这篇文章尝试为这些刚入行的新人提供一点帮助。 文章只介绍一些支付行业十几

资深支付架构师视角:实战从问题定义到代码落地的完整套路 2024-11-02 15:33

前言 今天从一个实际案例入手,介绍站在架构师的角度,如何识别并定义问题,提炼需求,技术方案选型,再到详细设计,最后利用AI的能力协助写出核心的代码,验证与调优。 解决问题存在一定的模式,也可以称之为框架,总结出自己的思考和解题框架,以后再碰到同类型的问题就可以如庖丁解牛一样容易。 很多年前,我写代码

Spring 实现 3 种异步接口 2024-10-18 09:07

大家好,我是苏三~ 如何处理比较耗时的接口? 这题我熟,直接上异步接口,使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性,处理结果仅返回单个值。在某些场景下,如果需要接口异步处理的同时,还持续不断地

重学SpringBoot3-集成Redis(五)之布隆过滤器 2024-10-08 11:24

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(五)之布隆过滤器 1. 什么是布隆过滤器? * 基本概念 适用场景 2. 使用 Redis 实现布隆过滤器 * 项目依赖 Redis 配置

设计模式第16讲——迭代器模式(Iterator) 2024-10-08 11:24

一、什么是迭代器模式 迭代器模式是一种行为型设计模式,它提供了一种统一的方式来访问集合对象中的元素,而不是暴露集合内部的表示方式。简单地说,就是将遍历集合的责任封装到一个单独的对象中,我们可以按照特定的方式访问集合中的元素。 二、角色组成 抽象迭代器(Iterator):定义了遍历聚合对象所需的方法

vue2路由和vue3路由区别及原理 2024-10-08 11:24

一、Vue2 与 Vue3 路由的区别 1. 创建路由实例方式的不同 Vue 2 中,通过 Vue.use() 注册路由插件,并通过 new VueRouter() 来创建路由实例。 import Vue from 'vue';import VueRouter from 'vue-router';i

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.