仿牛客网项目实战3:Spring入门

简介: spring一般指的是一个全家桶。

Spring


spring一般指的是一个全家桶。

84f2a0b1e8227aa3cd6545cbee003471_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

项目中只有浏览器一个客户端,所以项目中DataFlow是用不上的。

只是做基本的web开发springboot就可以了,build anything。

如果想做微服务那么就用springcloud,能够协调一切coordinate anything。

如果想做更多的客户端及集成,spring cloud data flow可以连接一切。


这些都是基于Spring Framework框架的。


Spring Framework


66c13a8923c9df82fae38b1fdc807d63_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_15,color_FFFFFF,t_70,g_se,x_16.png

IoC、AOP都是用来管理对象的思想。


Spring Core的核心

IoC/AOP

都是管理对象的思想,IoC是面向对象,AOP是面向切面的思想,所以有这两个思想能够管理一切对象。

Spring Data Access

用来管理数据库事务。

Web Servlet

使用SpringMVC来管理Web开发。

Integration继承

用来集成Email、AMQP消息队列、Security安全控制等等。

IoC

Spring所有功能都是可以说以IoC为基础的。


Inversion of Control

控制反转,是一种面向对象编程的思想。

通常关联对象是new一个对象a,然后a.setB创建B的对象,但是缺点就是A和B进行了耦合,如果项目变大了,那么就不方便维护。所以IoC是为了解决耦合度的问题。

f915903d008a04572d3af2dc60bec1bf_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

ioc是靠 Dependency Injection来实现的,即依赖注入。

而依赖注入是ioc容器实现的关键,本质上就是工厂。

e1ee26865873157c5c96eef67f865efc_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_13,color_FFFFFF,t_70,g_se,x_16.png

bean与bean之间的关联是在配置中体现的,降低了耦合度。

34044cb093a87750fc0e11ed1ea741a7_c3817398b34d4868b34488c2f9969a9c.png

@springbootapplication这个注解是由其他注解组成的。

fb97f7f7c32c751db889f078d56d517b_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_18,color_FFFFFF,t_70,g_se,x_16.png

按住control点进去可以发现构成这个注解的注解有哪些。

@componentscan就是配置类扫描,哪些类能被扫描呢,就是需要@Controller和@Service、@Repository等四个配置才能被自动扫描到。

如果是业务组件就需要@Service组件才能被扫描,如果是控制组件就需要@Controller。

【重要注解:①@controller(请求)、@Repository(数据库)、@Service(业务)和@Component(任意调用)可以使得spring容器扫描bean;可以直接使用application.getbean()的方式获得,也可以使用@Autowired依赖注入的方式;如果bean出现重名,可以使用name将其区分开,也可以使用@primary设置其优先级;默认创建的bean对象都是单例的,如果需要改变不是单例@singlone可以写成@prototype改变成多例的。】


如何证明这个容器存在呢,可以这么证明:

0ba871fe3f7041ed6b3e6fdec748a80c_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

这样子控制台可以看到输出了这个容器,是可见的,是存在的。那么如何运用这个容器去管理Bean呢?


现在写一个bean,现在假设要访问数据库,那么我建一个包专门用来管理访问数据库,这个包下建立接口等等。

377418d3d207fd1bccf13a0cc30daf06_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_18,color_FFFFFF,t_70,g_se,x_16.png


接口不能直接用,还得加一个接口的实现类。

然后增加这个接口的具体实现方法。


同时注意在类上加上注解,让程序自动扫描。

0b809ff1f3c810fc5c43f269386c4ef1_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

然后就可以从容器中获取到这个Bean了。

6a20a86607fdbd03af110dfaef0f13cb_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png


这样就成功获取到了Bean,并得到了结果。

这样做的好处:再次通过一个实例来观察。

846845d9840933e743e088287c089bbd_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_17,color_FFFFFF,t_70,g_se,x_16.png


做完上面这一张图需要注意加注解,同时这个时候因为我们是getBean去获取,那么此时满足条件的就有两个了,Bean容器就不知道给你哪一个了。

然后这个时候只需要在希望得到的Bean加一个注解就可以优先得到了。

91b7da8d8242abf042cbd76aef613998_bf36c95c23eb4e398da7013b50f85940.png

调用的Bean是依赖的接口,不依赖本身,则是面向接口的思想,就比较方便,但是也可能会带来一个问题,如果某一块不想要MyBatis,那么就需要强制容器进行返回就可以了。

27b91491f70d160410744f8a67e2242d_137b2eccf9b3478da61ad4a19848fa1d.png

除了上面这个方法,还可以通过加前缀强制转型。

ad00a5c3254957aed67ef2c8958b3ef1_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png


现在如果该多了一个service层,那么可以如 下图一样进行添加。

现在希望容器管理这个Bean销毁和初始化那些方法,那么想要容器调用这些方法需要添加@PostConstruct方法就可以了。通常在构造器后进行调用。

0321c37ba40f03fa39aa6c85dac2f468_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

557ea21009ea62e8fcd3bbede65df41c_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png


现在在测试类进行测试演示。

c613a69482fcce7612155b4c54573f80_dc57ed364ee4404eab60563d4028ac01.png

然后可以发现在控制台打印了这些方法。

27ebf311ef0e031d5251ebe6979cf873_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

然后通过打印台可以看出,这些Bean都是实例化一次的,只实例一次的。

开始被实例、初始化,然后结束后销毁。

就算调用两次,控制台也是出来一次的。

可以看出是单例的。


如果不希望是单例的,希望整个容器中有多个,那么就需要加一个注解。

4be087167cb8f554aac4a79d134c0321_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_13,color_FFFFFF,t_70,g_se,x_16.png

这样每次访问该Bean的时候都会加一个实例。

但是通常情况下都是单例的情况。


以上都是管理自己的Bean,那么如果想调用第三方的话,那么就需要自己写一个配置类,装配一个第三方的Bean。

配置类可以建一个包 config包。

5d1a125bdf2adbab681d00de76d22619_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

同时需要注意下图中的方法名就是Bean的名字。

14b30f7b8177776ab409bdef8209cd5d_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

这个时候也就说这个方法的返回类型将被装配到容器里进行反复运用。

然后再 在测试类中进行测试,再添加一个测试方法。

先声明类型然后进行getBean就可以了。下图中调用这个对象去初始化一个当前时间。

0a0e3ceca09fd2967dcaf9fee8da6417_fd742b9ce5224345bad5c4130c54e1af.png

f20c786beb74a084f010dbd6efcd7c8f_d54729a00ebe4d4ab2049887d3f85e90.png

上述讲的都是主动调用容器的方法。

但是一般是自动注入容器等。接下来讲 依赖注入。


只需要声明给当前的Bean注入Alpdao就可以了。

那么注入的话需要用到@Autowired注解。

然后加在一个成员变量之前。

那么就是说,希望容器把alphadao注入给这个属性,给我们直接使用就可以了。(DI依赖注入)

502bdc08cd524847d63a47d263a07a7a_9dd64d767580436094bff06a20fd33f7.png

发现可以打印出结果的。

e35b7ded13e16a2e46b4271585b0ce28_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

同理,alphaService也是可以的,SimpleDateFormat也是可以的。

71994c30bc6cb3d2e3aae1aaf40a7218_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_14,color_FFFFFF,t_70,g_se,x_16.png

729a8ab955d82622d12aa6d177e01d98_6f5c901067d846ff8d8c517475d90cc9.png

这个时候都取到了。

但如果想改注入的东西,比如说alphadao不要alphadao而是hibernate,那么就可以添加一个注释就可以了。(即忽视优先级)

6935d814449c1f866b621d85a88eb737_695a7767a3aa45df9fd5468a9e9e3d70.png

实际业务中:controller处理浏览器的请求,来调用service处理业务,然后service调用dao处理。彼此互相依赖的,他们的关系就可以通过依赖注入实现。

比如说现在需要注入alphadao给alphaserrvice。那么就可以在处理业务的时候调用service了。

b24b86b8be6d377749578222502dd957_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

然后写一个方法模拟查询的业务就可以了。

2e8bdebfec21e0b3d2c108978b5e3ee1_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

然后再controller中将service注入给他,然后处理一个查询请求的方法就可以了。

583cbf725f2af7daf0a90532d93bdbec_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

dcc4351ce1901630c42f51632cc993d5_4b140fbace6b4ac7bba7b144066a18aa.png


整理一下:首先调用controller,然后controller调用service中的find方法,然后find方法中又调用alohadao的方法,然后就是这么实现的。通过这样的例子理解DI的概念。

通过容器统一的管理,降低Bean之间的耦合度。

(可以看到,在controller层中,我们调用了service层的代码,却不是直接new一个对象,而是用@Autowired注解,并在类上使用了@Controller注解,这些注解帮助我们自动配置并注入对象,我们在使用时就不用new对象,从而减少代码耦合。)

ec003ebac9d39b02b98a2abf493a2fcb_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_16,color_FFFFFF,t_70,g_se,x_16.png

038764693706f2dc8f89a06f56a7a696_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_19,color_FFFFFF,t_70,g_se,x_16.png

相关文章
|
20天前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
192 2
|
5月前
|
人工智能 Java API
Spring AI 实战|Spring AI入门之DeepSeek调用
本文介绍了Spring AI框架如何帮助Java开发者轻松集成和使用大模型API。文章从Spring AI的初探开始,探讨了其核心能力及应用场景,包括手动与自动发起请求、流式响应实现打字机效果,以及兼容不同AI服务(如DeepSeek、通义千问)的方法。同时,还详细讲解了如何在生产环境中添加监控以优化性能和成本管理。通过Spring AI,开发者可以简化大模型调用流程,降低复杂度,为企业智能应用开发提供强大支持。最后,文章展望了Spring AI在未来AI时代的重要作用,鼓励开发者积极拥抱这一技术变革。
2069 71
Spring AI 实战|Spring AI入门之DeepSeek调用
|
6月前
|
安全 Java 数据库
Spring Security 实战指南:从入门到精通
本文详细介绍了Spring Security在Java Web项目中的应用,涵盖登录、权限控制与安全防护等功能。通过Filter Chain过滤器链实现请求拦截与认证授权,核心组件包括AuthenticationProvider和UserDetailsService,负责用户信息加载与密码验证。文章还解析了项目结构,如SecurityConfig配置类、User实体类及自定义登录逻辑,并探讨了Method-Level Security、CSRF防护、Remember-Me等进阶功能。最后总结了Spring Security的核心机制与常见配置,帮助开发者构建健壮的安全系统。
383 0
|
3月前
|
前端开发 Java API
基于 Spring Boot 3 与 React 的 Java 学生信息管理系统从入门到精通实操指南
本项目基于Spring Boot 3与React 18构建学生信息管理系统,涵盖前后端开发、容器化部署及测试监控,提供完整实操指南与源码,助你掌握Java全栈开发技能。
191 0
|
4月前
|
Java 关系型数据库 MySQL
【Spring】【事务】初学者直呼学会了的Spring事务入门
本文深入解析了Spring事务的核心概念与使用方法。Spring事务是一种数据库事务管理机制,通过确保操作的原子性、一致性、隔离性和持久性(ACID),维护数据完整性。文章详细讲解了声明式事务(@Transactional注解)和编程式事务(TransactionTemplate、PlatformTransactionManager)的区别与用法,并探讨了事务传播行为(如REQUIRED、REQUIRES_NEW等)及隔离级别(如READ_COMMITTED、REPEATABLE_READ)。
383 1
|
4月前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
513 0
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
6月前
|
存储 安全 Java
Spring Security 入门与详解
Spring Security 是 Spring 框架中的核心安全模块,提供认证、授权及防护功能。本文详解其核心概念,包括认证(Authentication)、授权(Authorization)和过滤器链(Security Filter Chain)。同时,通过代码示例介绍基本配置,如 PasswordEncoder、UserDetailsService 和自定义登录页面等。最后总结常见问题与解决方法,助你快速掌握 Spring Security 的使用与优化。
1510 0
|
10月前
|
存储 安全 Java
Spring Security 入门
Spring Security 是 Spring 框架中的安全模块,提供强大的认证和授权功能,支持防止常见攻击(如 CSRF 和会话固定攻击)。它通过过滤器链拦截请求,核心概念包括认证、授权和自定义过滤器。配置方面,涉及密码加密、用户信息服务、认证提供者及过滤器链设置。示例代码展示了如何配置登录、注销、CSRF防护等。常见问题包括循环重定向、静态资源被拦截和登录失败未返回错误信息,解决方法需确保路径正确和添加错误提示逻辑。
606 2
Spring Security 入门