IT评测·应用市场-qidao123.com

标题: 全网最详细的Spring入门教程 [打印本页]

作者: 商道如狼道    时间: 2024-12-9 07:37
标题: 全网最详细的Spring入门教程
为什么用Spring

什么是Spring

Spring 是一款开源的轻量级 Java 开发框架,旨在提高开发人员的开发服从以及体系的可维护性。
Spring的一个最大的目标就是使JAVA EE开发更加容易。同时,Spring之以是与Struts、Hibernate等单层框架不同,是因为Spring致力于提供一个以统一的、高效的方式构造整个应用,而且可以将单层框架以最佳的组合揉和在一起建立一个连贯的体系。可以说Spring是一个提供了更完善开发环境的一个框架,可以为POJO(Plain Ordinary Java Object)对象提供企业级的服务。
Spring的特性和上风

从Spring 框架的特性来看:
从使用Spring 框架的上风看:
相干资料

Spring的组件


Spring5.x 版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增长了用于异步响应式处理的 WebFlux 组件。

从最下层往上介绍
Spring Test

Spring 团队提倡测试驱动开发(TDD)。有了控制反转 (IoC)的资助,单元测试和集成测试变得更简单。
Spring 的测试模块对 JUnit(单元测试框架)、TestNG(类似 JUnit)、Mockito(主要用来 Mock 对象)、PowerMock(解决 Mockito 的问题好比无法模拟 final, static, private 方法)等等常用的测试框架支持的都比较好。而且还额外提供了一些基于 Spring 的测试功能,好比在测试 Web 框架时,模拟 Http 请求的功能。
包含Mock Objects, TestContext Framework, Spring MVC Test, WebTestClient。
源码对应模块如下:

Core  Container

Spring 框架的核心模块,也可以说是基础模块,主要提供 IoC 依赖注入功能的支持。由 Beans 模块、Core 核心模块、Context 上下文模块和 SpEL 表达式语言模块组成,没有这些核心容器,也不可能有 AOP、Web 等上层的功能。
对应源码模块如下:

AOP、Aspects、Instrumentation和Messaging

对应源码模块如下:

Data Access/Integration

对应源码模块:

Spring Web

对应源码模块如下:

Spring、SpringMVC、SpringBoot之间的关系

Spring 包含了多个功能模块(上面刚刚提到过),其中最紧张的是 Spring-Core(主要提供 IoC 依赖注入功能的支持) 模块, Spring 中的其他模块(好比 Spring MVC)的功能实现基本都需要依赖于该模块。
Spring MVC 是 Spring 中的一个很紧张的模块,主要赋予 Spring 快速构建 MVC 架构的 Web 程序的本领。MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、体现分离来组织代码。
使用 Spring 进行开发各种设置过于贫苦好比开启某些 Spring 特性时,需要用 XML 或 Java 进行显式设置。于是,Spring Boot 诞生了!
Spring 旨在简化 J2EE 企业应用程序开发。Spring Boot 旨在简化 Spring 开发(减少设置文件,开箱即用!)。
Spring Boot 只是简化了设置,如果你需要构建 MVC 架构的 Web 程序,你还是需要使用 Spring MVC 作为 MVC 框架,只是说 Spring Boot 帮你简化了 Spring MVC 的许多设置,真正做到开箱即用!
HelloWorld-xml

这里只是体现这是Spring第一个项目,以HelloWorld作为标注。现实需求是获取 用户列表信息,并打印执行日记
案例

案例源码点击这里
  1. <properties>
  2.         <maven.compiler.source>8</maven.compiler.source>
  3.         <maven.compiler.target>8</maven.compiler.target>
  4.         <spring.version>5.3.37</spring.version>
  5.         <aspectjweaver.version>1.9.6</aspectjweaver.version>
  6.     </properties>
  7.     <dependencies>
  8.         <dependency>
  9.             <groupId>org.springframework</groupId>
  10.             <artifactId>spring-context</artifactId>
  11.             <version>${spring.version}</version>
  12.         </dependency>
  13.         <dependency>
  14.             <groupId>org.springframework</groupId>
  15.             <artifactId>spring-core</artifactId>
  16.             <version>${spring.version}</version>
  17.         </dependency>
  18.         <dependency>
  19.             <groupId>org.springframework</groupId>
  20.             <artifactId>spring-beans</artifactId>
  21.             <version>${spring.version}</version>
  22.         </dependency>
  23.         <dependency>
  24.             <groupId>org.aspectj</groupId>
  25.             <artifactId>aspectjweaver</artifactId>
  26.             <version>${aspectjweaver.version}</version>
  27.         </dependency>
  28.     </dependencies>
复制代码
  1. public class User {
  2.     private String name;
  3.     private int age;
  4.     public User(String name, int age) {
  5.         this.name = name;
  6.         this.age = age;
  7.     }
  8.     public String getName() {
  9.         return name;
  10.     }
  11.     public void setName(String name) {
  12.         this.name = name;
  13.     }
  14.     public int getAge() {
  15.         return age;
  16.     }
  17.     public void setAge(int age) {
  18.         this.age = age;
  19.     }
  20. }
复制代码
  1. public class UserDaoImpl{
  2.     public List<User> findUserList() {
  3.         return Collections.singletonList(new User("seven", 18));
  4.     }
  5. }
复制代码
  1. public class UserServiceImpl {
  2.     private UserDaoImpl userDao;
  3.     public void setUserDao(UserDaoImpl userDao) {
  4.         this.userDao = userDao;
  5.     }
  6.     public List<User> findUserList() {
  7.         return userDao.findUserList();
  8.     }
  9. }
复制代码
  1. @Aspect
  2. public class LogAspect {
  3.     @Around("execution(* com.seven.springhelloworldxml.service.*.*(..))")
  4.     public Object businessService(ProceedingJoinPoint pjp) throws Throwable {
  5.         // get attribute through annotation
  6.         Method method = ((MethodSignature) pjp.getSignature()).getMethod();
  7.         System.out.println("execute method: " + method.getName());
  8.         // continue to process
  9.         return pjp.proceed();
  10.     }
  11. }
复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.     <bean id="userDao" >
  6.         
  7.     </bean>
  8.     <bean id="userService" >
  9.         <property name="userDao" ref="userDao"/>
  10.         
  11.     </bean>
  12.    
  13. </beans>
复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xmlns:aop="http://www.springframework.org/schema/aop"
  5.        xmlns:context="http://www.springframework.org/schema/context"
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/aop
  9. http://www.springframework.org/schema/aop/spring-aop.xsd
  10. http://www.springframework.org/schema/context
  11. http://www.springframework.org/schema/context/spring-context.xsd
  12. ">
  13.     <context:component-scan base-package="com.seven.springhelloworldxml" />
  14.     <aop:aspectj-autoproxy/>
  15.     <bean id="logAspect" >
  16.         
  17.     </bean>
  18.    
  19. </beans>
复制代码
  1. public class APP {
  2.     public static void main(String[] args) {
  3.         // create and configure beans
  4.         ApplicationContext context = new ClassPathXmlApplicationContext("aspects.xml", "spring.xml");
  5.         // retrieve configured instance
  6.         UserServiceImpl service = context.getBean("userService", UserServiceImpl.class);
  7.         // use configured instance
  8.         List<User> userList = service.findUserList();
  9.         // print info from beans
  10.         userList.forEach(a -> System.out.println(a.getName() + "," + a.getAge()));
  11.     }
  12. }
复制代码
运行结果:

怎样体现的Spring上风

控制反转 - IOC

查询用户(service通过调用dao查询pojo),本质上就是怎样创建User/Dao/Service?
  1. UserDaoImpl userDao = new UserDaoImpl();
  2. UserSericeImpl userService = new UserServiceImpl();
  3. userService.setUserDao(userDao);
  4. List<User> userList = userService.findUserList();
复制代码
Bean的创建和使用分离了。
  1. // create and configure beans
  2. ApplicationContext context = new ClassPathXmlApplicationContext("aspects.xml", "spring.xml");
  3. // retrieve configured instance
  4. UserServiceImpl service = context.getBean("userService", UserServiceImpl.class);
  5. // use configured instance
  6. List<User> userList = service.findUserList();
复制代码
更进一步,便能理解为何会有如下的知识点了
面向切面 - AOP

第二个需求:给Service所有方法调用添加日记(调用方法时),本质上是解耦问题;
  1. public List<User> findUserList() {
  2.     System.out.println("execute method findUserList");
  3.     return this.userDao.findUserList();
  4. }
复制代码
  1. /**
  2. * aspect for every methods under service package.
  3. */
  4. @Around("execution(* com.seven.springhelloworldxml.service.*.*(..))")
  5. public Object businessService(ProceedingJoinPoint pjp) throws Throwable {
  6.     // get attribute through annotation
  7.     Method method = ((MethodSignature) pjp.getSignature()).getMethod();
  8.     System.out.println("execute method: " + method.getName());
  9.     // continue to process
  10.     return pjp.proceed();
  11. }
复制代码
更进一步,便能理解为何会有如下的知识点了
Spring框架逐步简化开发

Java 设置方式改造

案例源码点击这里
在前文的例子中, 通过xml设置方式实现的,这种方式现实上比较贫苦; 我通过Java设置进行改造:
  1. @EnableAspectJAutoProxy
  2. @Configuration
  3. public class BeansConfig {
  4.     /**
  5.      * @return user dao
  6.      */
  7.     @Bean("userDao")
  8.     public UserDaoImpl userDao() {
  9.         return new UserDaoImpl();
  10.     }
  11.     /**
  12.      * @return user service
  13.      */
  14.     @Bean("userService")
  15.     public UserServiceImpl userService() {
  16.         UserServiceImpl userService = new UserServiceImpl();
  17.         userService.setUserDao(userDao());
  18.         return userService;
  19.     }
  20.     /**
  21.      * @return log aspect
  22.      */
  23.     @Bean("logAspect")
  24.     public LogAspect logAspect() {
  25.         return new LogAspect();
  26.     }
  27. }
复制代码
  1. public class APP {
  2.     public static void main(String[] args) {
  3.         // create and configure beans
  4.         ApplicationContext context = new AnnotationConfigApplicationContext(BeansConfig.class);
  5.         // retrieve configured instance
  6.         UserServiceImpl service = context.getBean("userService", UserServiceImpl.class);
  7.         // use configured instance
  8.         List<User> userList = service.findUserList();
  9.         // print info from beans
  10.         userList.forEach(a -> System.out.println(a.getName() + "," + a.getAge()));
  11.     }
  12. }
复制代码
这里简单提一下实现原理:
注解设置方式改造

案例源码点击这里
更进一步,Java 5开始提供注解支持,Spring 2.5 开始完全支持基于注解的设置而且也支持JSR250 注解。在Spring后续的版本发展倾向于通过注解和Java设置联合使用.
  1. @EnableAspectJAutoProxy
  2. @Configuration
  3. public class BeansConfig {
  4. }
复制代码
  1. @Repositorypublic class UserDaoImpl{
  2.     public List<User> findUserList() {
  3.         return Collections.singletonList(new User("seven", 18));
  4.     }
  5. }
复制代码
  1. @Service
  2. public class UserServiceImpl {
  3.     @Autowired
  4.     private UserDaoImpl userDao;
  5.     public List<User> findUserList() {
  6.         return userDao.findUserList();
  7.     }
  8. }
复制代码
  1. @Component
  2. @Aspect
  3. public class LogAspect {
  4.     @Around("execution(* com.seven.springhelloworldanno.service.*.*(..))")
  5.     public Object businessService(ProceedingJoinPoint pjp) throws Throwable {
  6.         // get attribute through annotation
  7.         Method method = ((MethodSignature) pjp.getSignature()).getMethod();
  8.         System.out.println("execute method: " + method.getName());
  9.         // continue to process
  10.         return pjp.proceed();
  11.     }
  12. }
复制代码
  1. public static void main(String[] args) {
  2.         // create and configure beans
  3.         ApplicationContext context = new AnnotationConfigApplicationContext("com.seven.springhelloworldanno");
  4.         // retrieve configured instance
  5.         UserServiceImpl service = context.getBean(UserServiceImpl.class);
  6.         // use configured instance
  7.         List<User> userList = service.findUserList();
  8.         // print info from beans
  9.         userList.forEach(a -> System.out.println(a.getName() + "," + a.getAge()));
  10.     }
复制代码
这里要提一嘴的是,现在大多数的Spring项目,基本都是这种方式。主要步骤就是:
1、对类添加@Component相干的注解,好比@Controller,@Service,@Repository
2、设置ComponentScan的basePackage, 好比在xml文件里设置, 或者在设置类中设置@ComponentScan("com.seven.springframework")注解,或者 直接在APP类中 new AnnotationConfigApplicationContext("com.seven.springframework")指定扫描的basePackage.
SpringBoot托管设置

Springboot现实上通过约定大于设置的方式,使用xx-starter统一的对Bean进行默认初始化,用户只需要很少的设置就可以进行开发了。
面试题专栏

Java面试题专栏已上线,欢迎访问。
那么可以私信我,我会尽我所能资助你。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4