Spring更简单的存取方法

news2024/9/24 14:32:23

Spring存对象

在Spring的创建和使用篇章里,提到了用bean标签来将对象标识到Spring里面,但是这样的方法过于麻烦,下面我们来介绍使用类注解来存储对象。

五大类注解存对象

Spring里面有五大类注解:

@Controller、@Service、@Repository、@Component、@Configuration

在介绍类注解的使用之前,要先说明一下bean的自动命名规则,为后面使用对象做准备。

五大类注解中bean的命名规则

我们在idea中的搜索里,搜索 AnnotationBeanNameGenerator 这个类,里面有一个 buildDefaultBeanName 方法,如下:

 在这个红框的方法里面描述了一个命名方式,并且这个方法是在jdk里面的,如下:

字符串为 null 和 空字符串 的情况会返回本身;

当字符串超过1个字符时,如果首字符和第二个字符都为大写,此时返回原字符串;

除上述情况之外,将字符串的首字符变为小写,返回字符串。

总结:如果类名的首字符和第二个字符都为大写,bean的名字为类名;

除此之外,bean的名字为,首字母变小写的类名。

我们用个例子展示一下:

    public static void main(String[] args) {
        String className1 = "UserName";
        String className2 = "UClass";
        System.out.println("UserName -> " + decapitalize(className1));
        System.out.println("UClass -> " + decapitalize(className2));
    }

此时它的输出为:

 和我们前面的结论相同。

Content标签

Spring为了提高访问类的效率,提供了一个Content标签(Content标签可以有多个),在标签里面,将使用类注解的类,所对应的包名写入其中,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    <!-- 在 base-package 里填入包名 -->
    <content:component-scan base-package="Demo"></content:component-scan>
</beans>

加入标签后,里面的包及其子包里面的类,只要加了类注解,就都被存储到Spring里面了。

使用类注解存储对象

上述的五个类注解的使用方法相同,此处就展示一个。

//该类属于 Demo 包,和前面的Content标签的包名相对应。
@Controller
public class StudentController {
    public void sayHi() {
        System.out.println("do StudentController sayHi");
    }
}

然后我们使用这个类(此处的使用为复杂版本),bean的名字规范前面已经说过,此处不说明为什么是“studentController”了。

public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        StudentController studentController = 
context.getBean("studentController", StudentController.class);
        studentController.sayHi();
    }

输出效果:

 输出和我们的预期一样。

不过在使用类注释的时候要注意几个点:

1. 在同一个包下(包括子包),在加类注释时,最好不要有两个类名相同的类,如果一定要有,要在注释后面加上value来区分。

如下:

@Controller(value = "UserController2")
public class UserController {
    public void sayHi() {
        System.out.println("Demo.Controller -> do UserController sayHi");
    }
}

这样在使用该对象时,在id栏填入这个value的值即可。

但是要注意:相同的类在使用时不能导入多个包,要至少有一个是使用包名.类名的方式来获取该类的对象。

public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController = 
context.getBean("userController", UserController.class);
        userController.sayHi();

        //使用 包名.类名 的方式获取重名的类的对象
        Demo.Controller.UserController userController1 =
                context.getBean("UserController2", Demo.Controller.UserController.class);
        userController1.sayHi();
    }

2. bean标签和Content标签可以同时使用。

3. 没有加类注解的类,即使属于Content的包名下,也不会存储到Spring里。

4. 使用了类注解,但是该类不属于Content标签的包名下,也不会存储到Spring里。

五大类注解的区别和规范

我们来看一下这个五个类注解的源码:
@Controller

 @Service

@Repository

@Configuration

可以看到 @Controller、@Service、@Repository、@Configuration这四个类注解都实现了@Component 注解。

也就说明,这五个注解的功能其实相差不大,但是为什么要分为五个注解呢?

因为需要类注解标识自己对应的类的功能。

@Controller -- 验证用户请求的正确性(安保)

@Service -- 编排和调度具体的执行方法(分配)

@Repository -- 和数据库做交互

@Component -- 组件,工具类

@Configuration -- 配置项,项目中的一些配置

在JavaEE的标准分层中规定,至少要有三层:

1. 控制层、2. 服务层、3. 数据持久层

如下图:

 上述的流程在Java开发手册里面也有说明,和上面基本相同,如下:

 总结:每个类注解都可以将对象存储到Spring里,分出五大类注解的原因是为了让程序员更好区分每个类的功能。

使用@Bean去存储对象

和前面的五大类注解不同,@Bean是一个方法注解,当这个方法返回了一个对象,并且该方法使用了@Bean注解,此时这个返回的对象就存储到了Spring里面。

重点一、只有当这个类使用了五大类注解时,里面的@Bean注解才会生效

如下:

@Controller
public class UserBeans {

    @Bean
    public User UserById() {
        User user = new User();
        user.setUid(1);
        user.setUsername("张三");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

@Bean的命名规则和五大类注解的命名规则不同,它的bean名字默认是方法名,他还可以起别名/起多个别名,并且起了别名之后就无法使用方法名了。

@Controller
public class UserBeans {
    //多个别名 name/value都可以
    @Bean(name = {"user1", "u1"})
    public User UserById() {
        User user = new User();
        user.setUid(1);
        user.setUsername("张三");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
    //单个别名 name/value都可以
    @Bean(value = "user")
    public User UserByName() {
        User user = new User();
        user.setUid(2);
        user.setUsername("李四");
        user.setPassword("123456");
        user.setAge(20);
        return user;
    }
}

重点二、如果多个类里面有多个方法,他们的返回类型、方法名相同,此时会发生方法覆盖,也就是后存储的类会覆盖掉前一个存储的类,若不想被覆盖就进行@Bean的重命名(起别名)。

如果想控制存储的顺序,可以使用@Order注解

@Order(1)
@Controller
public class UserBeans {
    @Bean
    public User UserByName() {
        User user = new User();
        user.setUid(2);
        user.setUsername("李四");
        user.setPassword("123456");
        user.setAge(20);
        return user;
    }
}

//另一个类中
@Order(10)
@Controller
public class UserBeans2 {
    @Bean
    public User UserByName() {
        User user = new User();
        user.setUid(100);
        user.setUsername("abcdefg");
        user.setPassword("123456");
        user.setAge(999);
        return user;
    }
}

@Order注解中,值越小,存储的优先级越高,也就是说,在上面提到的情况下,Order里面的值越大,该类的方法就可以覆盖掉其他类的方法。

重点三、如果方法里面有参数是无法进行存储的,因此,方法重载也是无法被存储的。

Spring取对象

@Autowired注解

@Autowired用于将对象注入,它有三种注入方式:

属性注入(常用)

使用方法:在属性上面加上进行注入@Autowired注解

被注入的类(后面不再展示):

@Service
public class UserService {
    public void sayHi() {
        System.out.println("do UserService sayHi");
    }
}

使用类:

@Controller
public class UserController {
    //属性注入
    @Autowired
    private UserService userService;
    public void sayHi() {
        System.out.println("do UserController sayHi");
        userService.sayHi();
    }
}

不过这个注入方式要注意:不能给被final修饰的属性注入。 

如下:

 总结:

属性注入的优点:方便快捷。

属性注入的缺点:

1. 无法给不可变(final修饰)对象注入

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

3. 有一定风险,由于使用比较简单,所以容易违背 单一设计原则

Setter注入

使用方法:在Setting方法上加 @Autowired 注解。

@Controller
public class UserController {

    //setter 注入
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi() {
        System.out.println("do UserController sayHi");
        userService.sayHi();
    }
}

同时这个注入方式也是无法给 final 修饰的属性注入的。

 Setter注入的优点:符合单一设计原则。

 Setter注入的缺点:

1. 无法给不可变类(被final修饰)注入

2. 使用 Setter注入 的对象可能被修改成其他对象。因为Setting是一个方法,它可以在任何时候被调用,然后传入其他的对象。

构造方法注入(Spring官方推荐)

使用方法:在构造方法上加 @Autowired 注解

@Controller
public class UserController {

    //构造方法注入
    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void sayHi() {
        System.out.println("do UserController sayHi");
        userService.sayHi();
    }
}

如果只需要注入一个对象,并且只有一个构造方法的情况下,可以不加 @Autowired  注解

@Controller
public class UserController {

    //构造方法注入
    private UserService userService;
    
    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void sayHi() {
        System.out.println("do UserController sayHi");
        userService.sayHi();
    }
}

构造方法注入的优点:

1. 可以对不可变对象(被final修饰)进行注入。

因为被final修饰的对象要么直接赋值,要么在构造方法赋值。

2. 不会在其他地方被修改。(构造方法调用一次就会创建一次对象)

3. 可以保证注入的对象被完全初始化。

4. 通用性更好,其他的框架也可以使用

@Resoutce注解

@Resoutce 注解和 @Autowired注解都可以实现对象的注入,但是他们是有一定区别的。

@Resoutce 和 @Autowired 的区别

1. @Autowired注解属于Spring,@Resoutce注解属于jdk。

2. @Autowired注解支持构造方法注入,@Resoutce注解不支持构造方法注入。

3. @Resoutce注解有更多的功能,比如:name、value...,@Autowired注解功能较少。

4. @Autowired是先查找类,再查找名称;@Resoutce是先查找名称,后查找类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/452377.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NeRF必读五:NeRF in the wild

前言 NeRF从2020年发展至今&#xff0c;仅仅三年时间&#xff0c;而Follow的工作已呈井喷之势&#xff0c;相信在不久的将来&#xff0c;NeRF会一举重塑三维重建这个业界&#xff0c;甚至重建我们的四维世界&#xff08;开头先吹一波&#xff09;。NeRF的发展时间虽短&#xf…

ubuntu 3060显卡驱动+cuda+cudnn+pytorch+pycharm+vscode

文章目录 运行环境&#xff1a;适用&#xff1a;思路&#xff1a;1.1 3060显卡驱动自动安装2.1 CUDA11.1.11)下载CUDA Toolkit 11.1 Update 1 Downloads2)contunue , 然后accept3)回车取消Driver安装&#xff0c;然后install4)添加环境变量5)确认是否安装成功 3.1 cudnn 8.1.11…

【git安装、使用、常用命令】

文章目录 一、git下载与安装二、git的使用1.初次运行配置git2、本地新建版本仓库3、提交代码 总结&#xff08;git 常用命令&#xff09; 一、git下载与安装 1、下载链接&#xff1a; Git&#xff08;Git 主程序&#xff09;https://git-scm.com/downloads 根据自身电脑操作系…

客户端请求耗时严重原因排查优化 (Nginx导致)

客户端请求耗时严重&#xff0c;初步从几个方面进行排查 1.检查网络连接&#xff0c;是否实现丢包&#xff0c;网络波动&#xff0c;网络拥堵等问题。 2.检查客户端请求耗时和project api 接口耗时差异&#xff0c;判断是nginx问题还是接口问题 如果是nginx耗时导致&#xff0c…

podman pull或者push http镜像遇到http: server gave HTTP response to HTTPS client

原因:Docker自从1.3.X之后docker registry交互默认使用的是HTTPS&#xff0c;但是搭建私有镜像默认使用的是HTTP服务&#xff0c;所以与私有镜像交时出现以上错误 解决方案&#xff1a; #增加以下配置 vi /etc/containers/registries.conf [[registry]] location "…

mac gitstats查看git提交记录

一、介绍&#xff1a; 进一步来讲&#xff0c;Gitstats它是一个git仓库分析软件&#xff0c;它可以检查仓库并生成历史数据的统计信息。可以帮助你查看git仓库的提交状态&#xff0c;根据不同维度分析计算&#xff0c;并自动生成数据图表。 官网介绍&#xff1a;http://gitst…

基于 DolphinDB 机器学习的出租车行程时间预测

DolphinDB 集高性能时序数据库与全面的分析功能为一体&#xff0c;可用于海量结构化数据的存储、查询、分析、实时计算等&#xff0c;在工业物联网场景中应用广泛。本文以纽约出租车行程时间预测为例&#xff0c;介绍如何使用 DolphinDB 训练机器学习模型&#xff0c;并进行实时…

python+vue古诗词鉴赏学习网站vue+django国学经典在线学习系统

国古典诗词&#xff0c;是中华传统文化的瑰宝&#xff0c;民族精神的精华&#xff0c;是中国传统文化的精粹,在中国璀灿的古代文化中占有重要的地位。古诗不仅内涵丰富、包罗万象、意境深邃,具有很高的审美价值和很强的艺术感染力,而且语言凝练、短小精悍,词句优美,韵体和谐,使…

大数据周会-本周学习内容总结011

开会时间&#xff1a;2023.04.23 15:00 线下会议 目录 01【spark】 02【es同步mysql】 03【下周任务】 01【spark】 尚硅谷大数据技术Spark教程-笔记01【Spark&#xff08;概述、快速上手、运行环境、运行架构&#xff09;】尚硅谷大数据技术Spark教程-笔记02【SparkCore&am…

vue2 路由相关知识点

文章目录 1. 搭建路由组件1.1 安装 vue-router1.2 配置路由 2. 使用路由3. 路由的跳转3.1 声明式导航3.2 编程式导航 4. 路由传参4.1 路由传递参数 : 字符串形式4.2 路由传递参数 : 对象写法4.3 路由传参相关面试题 5. meta 使用6. 重写 push 和 replace 方法 1. 搭建路由组件 …

6 计时器(六)

6.7 TMI编码器接口 Encoder Interface 编码器接口 编码器接口可接收增量&#xff08;正交&#xff09;编码器的信号&#xff0c;根据编码器旋转产生的正交信号脉冲&#xff0c;自动控制CNT自增或自减&#xff0c;从而指示编码器的位置、旋转方向和旋转速度 每个高级定时器和通…

(二十一)查找算法-插值查找

1 基本介绍 1.1 插值查找 插值查找算法又称插值搜索算法&#xff0c;是在二分查找算法的基础上改进得到的一种查找算法。 插值查找算法只适用于有序序列&#xff0c;换句话说&#xff0c;它只能在升序序列或者降序序列中查找目标元素。作为“改进版”的二分查找算法&#xf…

手动测试台架搭建,让你的车载测试更轻松

目录&#xff1a;导读 引言 1、概述 2、主要内容 3、汽车测试台架分类 4、汽车测试台架分类 5、汽车测试台架分类台架测试输人台架硬件搭建CANoe台架搭建 6、台架测试输入&#xff1f; 7、需求规范是功能测试用例设计来源测试结果的判断﹔包括∶客户需求(功能规范)需求分…

Redis框架与SpringBoot的整合及详细学习汇总

目录 springBoot整合Redis Redis 的优势 Redis安装 Redis数据类型 springboot操作Redis springboot 配置redis RedisTemplate及其相关方法 springBoot实现上传下载 RedisTemplate及其相关方法 springBoot实现上传下载 springBoot CORS&#xff08;跨域资源共享&#…

【C++11】简介、列表初始化、声明、范围for、STL中的一些变化

简介、列表初始化、声明、范围for、STL中的一些变化 文章目录 简介、列表初始化、声明、范围for、STL中的一些变化一、C11简介二、统一的列表初始化1.{ }初始化2.initializer_list容器 三、声明1.auto2.decltype3.nullptr 四、范围for循环五、STL中一些变化 一、C11简介 在2003…

虚拟数字人遇上ChatGPT,好看的皮囊和有趣的灵魂?

都说好看的皮囊千篇一律&#xff0c;有趣的灵魂万里挑一&#xff0c;博雅仔不禁好奇&#xff0c;到底有没有皮囊又好看&#xff0c;灵魂又有趣的人呢&#xff1f;二者能否得兼&#xff1f;答案是当然可以啊。 虽然在现实生活中&#xff0c;遇到这样的人需要静待缘分的安排&…

pg从磁盘读取文件

**瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;14 文档用途 了解存储管理器 详细信息 0. 相关数据类型 打开的每一个段用如下结构表示&#xff0c;pg中有MdfdVec数组并且记录了这个数组的…

微信小程序开发--利用和风天气API实现天气预报小程序

本来是参照《微信小程序开发实战》做一个天气预报小程序的&#xff0c;实际运行的时候提示错误&#xff0c;code 400&#xff0c;参数错误。说明问题应该出在查询API的语句上&#xff0c;没有返回结果。 查阅后才知道&#xff0c;可能书籍出版时间较早&#xff0c;现在的和风获…

大数据学习初级入门教程(十六) —— Hadoop 3.x 完全分布式集群的安装、启动和测试

好久没用 Hadoop 集群了&#xff0c;参考以前写的《大数据学习初级入门教程&#xff08;一&#xff09; —— Hadoop 2.x 完全分布式集群的安装、启动和测试_孟郎郎的博客-CSDN博客》和《大数据学习初级入门教程&#xff08;十二&#xff09; —— Hadoop 2.x 集群和 Zookeeper…

C++代码使用 gperftools 工具进行性能分析

文章目录 前言gperftools 是什么使用方法安装工具代码插桩引入工具代码修改关键代码完整示例编译链接启动分析程序 数据分析总结 前言 一直想用 gperftools 做一下性能方面的尝试&#xff0c;之前一直忙着开发&#xff0c;目前已经到了后期&#xff0c;忙里抽闲亲自操作一遍&…