相关推荐recommended
JavaEE 突击 4 - Spring 更简单的读取和存储对象(1)
作者:mmseoamin日期:2024-03-20

Spring 更简单的读取和存储对象 - 1

  • 一 . 前置工作
    • 1.1 创建一个 Maven 项目
    • 1.2 添加 Spring 依赖
    • 1.3 创建启动类
    • 1.4 添加 Spring 配置文件并设置 Bean 扫描的根路径
    • 二 . 存储 Bean 对象
      • 2.1 使用类注解
        • @Controller[控制器]
          • 不加注解能行吗 ?
          • 配置路径错误
          • @Service[服务层]
          • @Repository[仓库]
          • @Component[组件]
          • @Configuration[配置]
          • 常见问题
            • 标签方法与 配置扫描路径方法能混着用吗 ?
            • 为啥那么要这么多的类注解?
            • 类注解之间的关系
            • 关于 Bean 的命名规则问题
            • 扩展问题
            • 2.2 使用方法注解 [@Bean ](/Bean )
              • 2.2.1 方法注解要搭配类注解使用
                • context.getBean() 的两个参数
                • 方法注解 , 能不能放到类上面呢 ?
                • 2.3.2 方法注解重命名
                  • 方法注解遇见方法重载
                  • 我们在给方法注解重命名之后 , 如果 getBeans 方法第一个参数填方法名 , 还能成功执行吗
                  • 2.3.3 小结

                    大家好 , 这个专栏给大家介绍一下 Java 家族的核心产品 - SSM 框架

                    Java 语言能走到现在 , 仍然屹立不衰的原因 , 有一部分就是因为 SSM 框架的存在

                    接下来 , 博主会带大家了解一下 Spring、Spring Boot、Spring MVC、MyBatis 相关知识点

                    并且带领大家进行环境的配置 , 让大家真正用好框架、学懂框架

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),在这里插入图片描述,第1张

                    一 . 前置工作

                    我们之前存储 Bean 的时候 , 比较麻烦 , 需要在 resources 目录底下配置 spring-config.xml , 也就是需要在 spring-config.xml 中添加一行 bean 注册对象才行
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第2张
                    现在我们可以通过 注解 的方式简化操作
                    但是我们需要进行一些前置操作

                    1.1 创建一个 Maven 项目

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第3张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第4张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第5张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第6张

                    1.2 添加 Spring 依赖

                    我们需要添加两个依赖 :

                    1. spring-context
                    2. spring-beans

                    接下来 , 把这段代码复制到 pom.xml 里面

                    
                        
                            org.springframework
                            spring-context
                            5.2.3.RELEASE
                        
                        
                            org.springframework
                            spring-beans
                            5.2.3.RELEASE
                        
                    
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第7张
                    记得刷新一下
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第8张

                    1.3 创建启动类

                    创建源文件
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第9张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第10张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第11张

                    1.4 添加 Spring 配置文件并设置 Bean 扫描的根路径

                    在 resources 目录下面创建出 spring-config.xml 文件
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第12张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第13张
                    然后把这段代码复制进去

                    
                    
                        
                    
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第14张
                    接下来添加这条语句
                    这句话的意思就是 : 配置 存储 Bean 对象的扫描路径
                    意思就是扫描这个路径下面带五大注解的对象 , 发现带五大注解的对象就把他存放到 Spring 里面

                    
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第15张
                    所以我们的最终的 spring-config.xml 就变成了

                    
                    
                        
                    
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第16张
                    注意 : 我们需要修改一个位置
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第17张
                    那么这个位置该怎么判断到底输入什么呢 ?
                    我们需要自己创建个包
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第18张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第19张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第20张
                    接下来 , 我们就把 spring-config.xml 改成

                    
                    
                        
                    
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第21张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第22张
                    那么大家注意 : 如果我们不写这条语句 , 就找不到对应的带有注解标签的对象了
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第23张
                    运行一下
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第24张

                    二 . 存储 Bean 对象

                    将 Bean 对象更简单的存储到 Spring , 就需要使用注解 : 这个注解就是一个声明 , 分成两类

                    1. 类注解 : @Controller、@Service、@Repository、@Component、@Configuration
                    2. 方法注解 : @Bean

                    无论是哪种注解 , 都表示当前的 类/方法 具备某种能力
                    我们之前学过 Servlet , 里面就使用过 @WebServlet 注解

                    2.1 使用类注解

                    @Controller[控制器]

                    我们在实验这个方法之前 , 再创建一个包
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第25张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第26张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第27张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第28张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第29张
                    这个 Controller 什么意思呢 , 其实它就像是我们的机场安检 , 控制着用户的入口和出口 , 是我们第一道防线 , 所以它是用来跟前端进行交互的 , 验证前端传递的参数 [安全检查]
                    我们来写一个普通的方法

                    package com.ethan.controller;
                    public class UserController {
                        public void doUserController() {
                            System.out.println("do UserController");
                        }
                    }
                    

                    但是目前还是有点问题 , 我们的 spring-config.xml 里面设置的根路径是 com.ethan.service , 但是我们现在的目录是 com.ethan.controller , 所以我们需要修改一下 , 修改成com.ethan , 这样就可以检索到 service 和 Controller了

                    
                    
                        
                    
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第30张
                    然后把 UserController 里面加上注解
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第31张

                    package com.ethan.controller;
                    import org.springframework.stereotype.Controller;
                    @Controller
                    public class UserController {
                        public void doUserController() {
                            System.out.println("do UserController");
                        }
                    }
                    

                    接下来设置一下启动类
                    先把步骤列出来

                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            // 2. 使用 getBean 得到 Bean 对象
                            // 3. 操作 Bean 对象
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第32张

                    import com.ethan.controller.UserController;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:类名的小驼峰
                            // 第二个参数:类名.class
                            UserController userController = context.getBean("userController",UserController.class);
                            
                            // 3. 操作 Bean 对象
                            userController.doUserController();
                        }
                    }
                    
                    不加注解能行吗 ?

                    那我们要是把注解注释了呢 ? 会发生什么 ?
                    我们把注解注释掉之后 , 他就是一个普通的方法了
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第33张

                    配置路径错误

                    假如我们把配置的路径改成 com.ethan.userController 呢 ?
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第34张
                    那要是把扫描路径改成 com.ethan.service 路径下面呢
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第35张
                    这是因为我们的 UserController 对象是存储在 com.ethan.controller 路径下面的 , 而我们把扫描路径改成了 com.ethan.service , 由于 controller 与 service 是平级关系 , 所以是扫描不到的 , 我们只需要把扫描路径改为 com.ethan , 这样 controller 以及 service 路径下面的带有注解的对象就会被扫描到了
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第36张


                    还有一个隐藏的小问题 , 我们这个 sayHello 方法为什么不能加 static 呢 ?
                    我们可以这样理解 , 我们使用 Spring 的目的就是把对象放到 Spring 里面去存储 , 那你如果加了 static , 就代表我们可以在对应的类里面去创建对象 , 这不又回到了我们之前的问题吗 , 把某个对象的生死权决定给了当前类 , 导致代码耦合度很大 , 我们暂且可以这样思考 , 其实这是 JVM - Spring 相关联的知识点 , 以后会给大家讲解


                    那么目前我们创建 Spring 已经有两种方法了
                    第一种 : 在 spring-config.xml 里面添加 对象

                    这样的好处就是我们可以清晰地看到我们的 Spring 项目里面创建了几个对象
                    第二种 : 在 spring-config.xml 里面添加 , 这样的好处是功能更加容易的创建 Spring 对象
                    总而言之 , 我们还是第二种方法更香一点 , 因为我们好像统计创建了几个对象也没啥意义 , 方便使用才是最香的

                    @Service[服务层]

                    服务层的作用是 服务调用的编排和汇总的接口

                    假如我们有这个场景 : 用户修改头像 , 然后用户积分 + 1

                    那么我们的编排就是 到底是先调用 修改数据表里面的头像字段 还是 用户积分 +1 呢 ? 那当然是先修改头像才能积分 +1

                    汇总就是 修改用户头像的请求过来之后 , 我们会在服务层里面实现这两个接口的调用 , 也就是在一个服务 / 方法里面 , 就把我后端需要更新的两张表所有的接口都在这个方法里面实现了 , 这就是汇总

                    但是他并不是最终去实现的 , 他就相当于医院的导诊台 , 它告诉你应该怎么走
                    那么我们来检验一下 , 看看这个 @Service 是否也能去存储 Bean 对象
                    我们在 com.ethan.service 里面新建 UserService 类
                    UserService.java

                    package com.ethan.service;
                    import org.springframework.stereotype.Service;
                    @Service
                    public class UserService {
                        public void doUserService() {
                            System.out.println("do UserService");
                        }
                    }
                    

                    目前我们已经实现了把 @Service 存储到 Spring 里面的操作
                    接下来 , 我们去启动类检验一下

                    import com.ethan.service.UserService;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:类名的小驼峰
                            // 第二个参数:类名.class
                            UserService userService = context.getBean("userService", UserService.class);
                            // 3. 操作 Bean 对象
                            userService.doUserService();
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第37张
                    这就说明我们可以把 @Service 修饰的类存到 Spring 里面
                    那么我们把注解去掉呢 , 还会成功吗 ?
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第38张

                    @Repository[仓库]

                    我们的 Repository 指的是数据仓库 , 是直接跟数据库打交道的 , 也就是直接操作数据库的
                    这个阶段才是真正干实事的人
                    UserRepository.java

                    package com.ethan.repository;
                    import org.springframework.stereotype.Repository;
                    @Repository
                    public class UserRepository {
                        public void doRepository() {
                            System.out.println("do UserRepository");
                        }
                    }
                    

                    启动类

                    import com.ethan.repository.UserRepository;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:类名的小驼峰
                            // 第二个参数:类名.class
                            UserRepository userService = context.getBean("userRepository", UserRepository.class);
                            // 3. 操作 Bean 对象
                            userService.doRepository();
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第39张

                    @Component[组件]

                    组件一般是和业务关系不大的 , 它是用来辅助开发的 , 假如我们的业务里面 , 有一个密码加密类 , 他和业务虽然有点关系 , 但是关系不大 , 就可以称为是组件 , 组件也可以认为是我们的通用化的工具类
                    UserComponent.java

                    package com.ethan.component;
                    import org.springframework.stereotype.Component;
                    @Component
                    public class UserComponent {
                        public void doUserComponents() {
                            System.out.println("do UserComponent");
                        }
                    }
                    

                    启动类

                    import com.ethan.component.UserComponent;
                    import com.ethan.repository.UserRepository;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:类名的小驼峰
                            // 第二个参数:类名.class
                            UserComponent userComponent = context.getBean("userComponent", UserComponent.class);
                            // 3. 操作 Bean 对象
                            userComponent.doUserComponents();
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第40张

                    @Configuration[配置]

                    当前项目的所有配置都会放在这里
                    UserConfiguration.java

                    package com.ethan.configuration;
                    import org.springframework.context.annotation.Configuration;
                    @Configuration
                    public class UserConfiguration {
                        public void doUserConfiguration() {
                            System.out.println("do UserConfiguration");
                        }
                    }
                    

                    启动类

                    import com.ethan.component.UserComponent;
                    import com.ethan.configuration.UserConfiguration;
                    import com.ethan.repository.UserRepository;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:类名的小驼峰
                            // 第二个参数:类名.class
                            UserConfiguration userConfiguration = context.getBean("userConfiguration", UserConfiguration.class);
                            // 3. 操作 Bean 对象
                            userConfiguration.doUserConfiguration();
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第41张

                    常见问题

                    标签方法与 配置扫描路径方法能混着用吗 ?

                    答案是 : 能
                    这种需求也是会有的 , 比如 : 我们需要一个对象 , 但是这个对象并不存储在 com.ethan 目录底下
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第42张
                    那么这时候 , 我们就可以自己创建一个 Bean 标签了
                    在此之前 , 我们先做一下准备
                    在 com 包新建一个 Other 类 , 这样的话 Other 类就在 com.ethan 之外了 , 配置的扫描路径就扫描不到 Other 类了 , 这样我们就可以通过 bean 标签存储 other 对象了
                    那么我们的 spring-config.xml 应该添加 bean 标签

                    
                    
                        
                        
                    
                    

                    先来编写一下 other 类的代码

                    package com;
                    public class Other {
                        public void otherMethod() {
                            System.out.println("bean 标签可以和 content 标签一起使用");
                        }
                    }
                    

                    在启动类里面运行一下

                    import com.Other;
                    import com.ethan.controller.UserController;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:类名的小驼峰
                            // 第二个参数:类名.class
                            UserController userController = context.getBean("userController",UserController.class);
                            Other other = context.getBean("other",Other.class);
                            // 3. 操作 Bean 对象
                            userController.doUserController();
                            other.otherMethod();
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第43张

                    为啥那么要这么多的类注解?

                    Spring 实际上就类似于工厂的模式 , 在工厂里面 , 没有一个人能够样样精通 , 所以一项大的任务需要很多人齐心协力一起完成 , 也就是说把整个项目拆开 , 分成很多个类去完成
                    本质上就是把一个整体的项目 , 拆成很多模块 , 进行"模块化"处理
                    那么为什么需要怎么多的类注解也是相同的原因,就是让程序员看到类注解之后,就能直接了解当前类的用途,比如:
                    @Controller:表示的是业务逻辑层;
                    @Service:服务层;
                    @Repository:持久层;
                    @Configuration:配置层。
                    就比如说 , 前端发过来的数据 , 一般都是这样走的 , 大家各司其职

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第44张

                    类注解之间的关系

                    我们也可以对注解进行 Ctrl + 单击 的操作
                    先看 @Controller
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第45张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第46张
                    这个 @Component 是组件的意思
                    那么其实就代表我们的 @Controller 是使用了 @Component 的功能的
                    我们再来看看其他的
                    @Service :
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第47张
                    @Repository :
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第48张
                    @Configuration :
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第49张
                    结论 : @Controller @Service @Repository @Configuration 跟 @Component 都是同宗的

                    从逻辑上来说 , @Component 是 @Controller @Service @Repository @Configuration 的父类

                    @Controller @Service @Repository @Configuration 都是基于 @Component 实现的 , 他们的作用都是将 Bean 存储到 Spring 中

                    关于 Bean 的命名规则问题

                    命名规则 : 默认情况下 , 使用 5 大类注解的 Bean 名称命名规则是 将类名首字母小写 的规则
                    例如 : UserController -> userController
                    那么为什么要使用 类名首字母小写的规则啊 ?
                    举一个特殊情况 :
                    我们新建一个包 , 叫做 namequestion , 还是创建在 com.ethan 下面
                    然后在这个包底下新建一个类 , 叫做 NameQuestion , 但是有的同学有点懒 , 偷奸耍滑 , 心思直接起一个名字叫做 NQuestion 吧 , 也能见名思意
                    接下来编写代码
                    NQuestion.java

                    package com.ethan.namequestion;
                    import org.springframework.stereotype.Controller;
                    @Controller
                    public class NQuestion {
                        public void method() {
                            System.out.println("测试 bean 命名问题");
                        }
                    }
                    

                    接下来在启动类中运行

                    import com.ethan.namequestion.NQuestion;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            NQuestion nQuestion = context.getBean("nQuestion", NQuestion.class);
                            // 3. 操作 Bean 对象
                            nQuestion.method();
                        }
                    }
                    

                    运行一下 , 发现傻眼了 , 怎么报错了 ??? 一定是编译器坏了 , 你不死心 , 又存储了 UserController 对象试试
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第50张
                    怎么还一个报错一个不报错呢 ?
                    原因就出现在我们的命名上
                    Spring 中 , 针对于类名

                    1. 首字母是大写 , 第二个字母不是大写 : 首字母小写获取 Bean
                    2. 首字母 第二个字母都是大写 : 使用原类名获取 Bean

                    UserController 是 首字母是大写 , 第二个字母不是大写 的情况 , 我们只需要采用类名小驼峰的形式 , 而 NQuestion 是 首字母 第二个字母都是大写 这种情况 , 所以需要直接使用类名
                    那我们现在知道为什么了 , 就改正一下看看能否成功吧
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第51张
                    那么我们也可以带大家看一下源码 , 再理解一下理解这个问题
                    由于我们的 Spring 源码更加复杂 , 所以直接 Ctrl + 单击 的形式已经不太好用了
                    所以我们可以找到问题的关键 : BeanName
                    然后进行搜索 (也可以连续按两次 shift)
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第52张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第53张
                    我们只需要看相对应的类即可 , 类是包含方法的 , 所以找到类就能看到对应的方法 , 所以不用刻意看方法 , 接口更不用看了 , 接口还要等着别人实现呢
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第54张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第55张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第56张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第57张
                    然后看代码
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第58张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第59张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第60张
                    这里面还有一个非常有趣的事
                    当前页面还在 Spring 的源码里面
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第61张
                    接下来调用的 decapitalize 方法就是来自于 JDK 里面的方法了
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第62张
                    因为这个方法来自于 JDK , 那么这个类的方法 , 我们还可以进行调用
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第63张

                    import java.beans.Introspector;
                    public class Test {
                        public static void main(String[] args) {
                            String str1 = "UserController";//第一个字母大写,第二个字母小写->首字母小写
                            String str2 = "NQuestion";//第一个字母 第二个字母都大写->原名称
                            str1 = Introspector.decapitalize(str1);
                            str2 = Introspector.decapitalize(str2);
                            System.out.println(str1);//userController
                            System.out.println(str2);//NQuestion
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第64张


                    扩展问题

                    有一道这样的面试题 : session 在分布式系统里面 , 用户的会话信息是怎样保存的 ?
                    我们正常情况下是这样的 , 用户与服务器是连接状态
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第65张
                    那么我们采用分布式的话 , 就变成这个样子了
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第66张
                    我们新添加了两个服务器 , 假如之前最多能同时容纳 100 人访问 , 那么现在就支持 300 人进行访问了
                    用户登录 , 发送请求给服务器
                    但是存在一个问题 , 我们之前是在 A 服务器登录的 , A 服务器里面存储了该用户的会话信息

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第67张
                    在分布式系统里面 , 采用的是 负载均衡策略 , 我们不指定的话 , 就是默认轮循 , 就是这次访问服务器1 , 下次就访问服务器2 , 下次访问服务器3 , 再访问服务器1 , 周而复始 , 那么这样就有个问题 , 我们的用户这次访问的是服务器2 , 服务器2 并没有存储用户的信息 , 所以会让用户重新登录 , 但是这个用户刚刚已经登陆了啊 .
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第68张
                    那么我们是这样处理的 , 让这三个服务器都连接同一个数据库 , 连接到某个服务器的时候 , 去数据库查询登录信息
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第69张

                    2.2 使用方法注解 @Bean

                    2.2.1 方法注解要搭配类注解使用

                    类注解是添加到某个类上的,而方法注解是放到某个方法上的
                    我们可以使用 Bean 注解将方法返回的对象存入到 Spring 里面
                    我们来试验一下方法注解
                    使用方法注解的目的就是将方法返回的对象存入到 Spring 里面 , 那么我们就可以新建一个 User 类
                    然后再写一个方法 , 将 User 类实例化之后返回
                    新建一个包 , 叫做 model , 然后在 model 包底下新建一个 User 类

                    package com.ethan.model;
                    public class User {
                        private int id;
                        private String name;
                        private int age;
                        public int getId() {
                            return id;
                        }
                        public void setId(int id) {
                            this.id = id;
                        }
                        public String getName() {
                            return name;
                        }
                        public void setName(String name) {
                            this.name = name;
                        }
                        public int getAge() {
                            return age;
                        }
                        public void setAge(int age) {
                            this.age = age;
                        }
                        @Override
                        public String toString() {
                            return "User{" +
                                    "id=" + id +
                                    ", name='" + name + '\'' +
                                    ", age=" + age +
                                    '}';
                        }
                    }
                    

                    接下来 , 新建一个包 userbean 用来测试我们的方法注解
                    然后在这个包底下新建一个类 : UserBean.java

                    package com.ethan.userbean;
                    import com.ethan.model.User;
                    import org.springframework.context.annotation.Bean;
                    public class UserBean {
                        public User func() {
                            // 构建测试数据
                            User user = new User();
                            user.setName("安陵容");
                            user.setAge(18);
                            user.setId(1);
                            return user;
                        }
                    }
                    

                    那么我们想要把这个方法的返回值作为对象放到 Spring 里面 , 就需要在方法上面加上 @Bean 注解

                    package com.ethan.userbean;
                    import com.ethan.model.User;
                    import org.springframework.context.annotation.Bean;
                    public class UserBean {
                        @Bean
                        public User func() {
                            // 构建测试数据
                            User user = new User();
                            user.setName("安陵容");
                            user.setAge(18);
                            user.setId(1);
                            return user;
                        }
                    }
                    

                    目前我们把 func() 的返回值已经存储到 Spring 里面了 , 接下来我们就可以去启动类里面打印相对应的结果了
                    但是这又出现问题了 , context.getBean(); 的第一个参数是什么 ?
                    先蒙一个方法名

                    import com.ethan.userbean.UserBean;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            UserBean userBean = context.getBean("func",User.class);//类名第一个字母大写 , 第二个字母小写的情况
                            // 3. 打印 Bean 对象
                            System.out.println(userBean);
                        }
                    }
                    

                    运行发现报错了
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第70张
                    这是因为我们的方法注解要搭配我们之前的五大类注解一起使用
                    UserBean.java

                    package com.ethan.userbean;
                    import com.ethan.model.User;
                    import org.springframework.context.annotation.Bean;
                    import org.springframework.stereotype.Controller;
                    // 方法注解要搭配五大类注解使用
                    @Controller
                    public class UserBean {
                        @Bean
                        public User func() {
                            // 构建测试数据
                            User user = new User();
                            user.setName("安陵容");
                            user.setAge(18);
                            user.setId(1);
                            return user;
                        }
                    }
                    

                    启动类 :

                    import com.ethan.model.User;
                    import com.ethan.userbean.UserBean;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:方法名
                            // 第二个参数:所对应的类名
                            User user = context.getBean("func",User.class);
                            // 3. 打印 Bean 对象
                            System.out.println(user);
                        }
                    }
                    

                    运行一下
                    没问题了 , 成功打印
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第71张
                    这样做的原因其实也很简单 , @Bean 注解是针对于方法的 , 但是类里面的方法太多了 , 方法的返回对象要存储到 Spring 里面 , 但是咱们不能扫描所有的方法 , 因为要是扫描所有类里面的所有方法太浪费时间了 , 那么就这样设计 : 当某个类里面某个方法要存储到 Spring 里面的话 , 只需要给当前的类加个五大类注解标识一下 , 告诉 Spring 一声我这个类里面有可能有方法注解 , 也就是有某个方法需要把返回的对象存到 Spring 里面

                    context.getBean() 的两个参数

                    第一个参数是方法名 , 第二个参数是这个方法返回值所对应的类.class , 我们可以试验一下
                    我们把方法名改成 error , 然后启动类中不变 , 就会报错
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第72张
                    反之同理
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第73张

                    方法注解 , 能不能放到类上面呢 ?

                    类注解是不能放到方法上面的
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第74张
                    方法注解也不能放在类上面
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第75张

                    2.3.2 方法注解重命名

                    假如在同一个类当中有两个方法 , 他们都返回 User 对象

                    package com.ethan.userbean;
                    import com.ethan.model.User;
                    import org.springframework.context.annotation.Bean;
                    import org.springframework.stereotype.Controller;
                    @Controller
                    public class UserBean {
                        @Bean
                        public User func1() {
                            // 构建测试数据
                            User user = new User();
                            user.setName("安陵容");
                            user.setAge(18);
                            user.setId(1);
                            return user;
                        }
                        @Bean
                        public User func2() {
                            User user = new User();
                            user.setName("沈眉庄");
                            user.setAge(20);
                            user.setId(2);
                            return user;
                        }
                    }
                    

                    启动类

                    import com.ethan.model.User;
                    import com.ethan.userbean.UserBean;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:方法名
                            // 第二个参数:所对应的类名
                            User user1 = context.getBean("func1",User.class);
                            System.out.println(user1);
                            User user2 = context.getBean("func2",User.class);
                            System.out.println(user2);
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第76张
                    在 Spring 中 , 存储 Bean 的方式如下 :

                    HashMap
                    一个 key 对应一个 value
                    key 就是方法名 , value就是方法返回的对象
                    

                    所以通过不同的方法名 , 我们就能拿到不同的对象
                    那么我们假如在别的类当中 , 也有个方法叫做 func1 , 我们刚介绍完 , 一个 方法名 对应一个 value , 那么现在出现了同名的情况 , 是返回两个还是一个都不返回呢 ?
                    那么我们就来实验一下 , 在 userbeans 包底下新建 Test 类 , 然后在里面写一个也叫做 func1 的方法 , 但是方法里面的内容不同

                    package com.ethan.userbean;
                    import com.ethan.model.User;
                    import org.springframework.context.annotation.Bean;
                    import org.springframework.stereotype.Controller;
                    @Controller
                    public class Test {
                        @Bean
                        public User func1() {
                            User user = new User();
                            user.setName("甄嬛");
                            user.setAge(21);
                            user.setId(3);
                            return user;
                        }
                    }
                    

                    接下来编写启动类

                    import com.ethan.model.User;
                    import com.ethan.userbean.UserBean;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:方法名
                            // 第二个参数:所对应的类名
                            User user1 = context.getBean("func1",User.class);
                            System.out.println(user1);
                        }
                    }
                    

                    运行一下 , 看看是谁被召见了
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第77张
                    那么我们的甄嬛是不希望看到安陵容得宠的 , 甄嬛就要使出一点手段 , 他就给安陵容起外号 , 这样皇上听到一些不好的就不去宠幸他了 , 那么这就是 Bean 注解的重命名
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第78张
                    我们看一下源码
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第79张
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),第80张
                    那我们就用一下 @Bean(value=“zhenhuan”) 试一试
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第81张
                    其实都不用这么麻烦 , 括号里面直接写名字就行
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第82张
                    最牛逼的就是这种用法
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第83张
                    所以我们的 @Bean 重命名有四种写法

                    @Bean(name = "zhenhuan")
                    @Bean(value = "zhenhuan")
                    @Bean("zhenhuan")
                    @Bean(name = {"zhenhuan","huaner","xifei"})
                    
                    方法注解遇见方法重载

                    假如我们的 UserBeans 类里面进行了方法重载

                    package com.ethan.userbean;
                    import com.ethan.model.User;
                    import org.springframework.context.annotation.Bean;
                    import org.springframework.stereotype.Controller;
                    @Controller
                    public class UserBean {
                        @Bean("anlingrong")
                        public User func() {
                            // 构建测试数据
                            User user = new User();
                            user.setName("安陵容");
                            user.setAge(18);
                            user.setId(1);
                            return user;
                        }
                        @Bean("shenmeizhuang")
                        public User func(int id) {
                            User user = new User();
                            user.setName("沈眉庄");
                            user.setAge(20);
                            user.setId(id);
                            return user;
                        }
                    }
                    

                    方法重载的概念 : 方法名相同 , 参数列表不同 , 与返回值无关
                    接下来 , 我们在启动类打印沈眉庄的信息

                    import com.ethan.model.User;
                    import com.ethan.userbean.UserBean;
                    import org.springframework.context.ApplicationContext;
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    public class App {
                        public static void main(String[] args) {
                            // 1. 得到上下文对象
                            ApplicationContext context =
                                    new ClassPathXmlApplicationContext("spring-config.xml");
                            // 2. 使用 getBean 得到 Bean 对象
                            // 第一个参数:方法名
                            // 第二个参数:所对应的类名
                            User user1 = context.getBean("shenmeizhuang",User.class);
                            System.out.println(user1);
                        }
                    }
                    

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第84张
                    这难道是方法重载搞的鬼 ? 我们把沈眉庄对应的方法名改为 func2
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第85张
                    那么我们来看一下这个报错信息什么意思
                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第86张
                    没有 int 类型的合格 bean 可用 : 期望至少有一个合格的自动装配候选 bean , 说一千道一万 , 其实就是使用方法注解就不能搭配函数参数使用
                    这是因为我们的参数里面带了个 id , 而这个 id 是没法办法传进去的 , 所以只会一直调用无参数的方法
                    所以总结一下 : @Bean 方法注解只能使用在无参的方法上 (Spring初始化存储时,没办法提供相应参数) 。

                    我们在给方法注解重命名之后 , 如果 getBeans 方法第一个参数填方法名 , 还能成功执行吗

                    JavaEE 突击 4 - Spring 更简单的读取和存储对象(1),image.png,第87张
                    所以 @Bean 重命名之后,使用方法名就不能再获取 Bean 对象了。

                    2.3.3 小结

                    1. @Bean 方法注解的命名规则 : 方法名

                    2. @Bean 方法注解必须要搭配五大类注解一起使用 , 不然注解不进去

                    3. @Bean 方法注解只能使用在无参的方法上( Spring 初始化存储时 , 没办法提供相应参数)

                    4. @Bean 重命名的常见三种写法

                      @Bean(name = "student")
                      @Bean("student")
                      @Bean(name = {"student","teacher","master"})
                      
                    5. @Bean 重命名之后,使用方法名就不能再获取 Bean 对象了。