# spring-study **Repository Path**: mnmnwq/spring-study ## Basic Information - **Project Name**: spring-study - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-07-23 - **Last Updated**: 2021-07-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: spring学习, java学习 ## README ## 目录结构 #### spring-01-ioc 传统开发目录结构 #### spring-02-hellospring 第一个spring程序 #### spring-03-di DI依赖注入几种方式 #### spring-04-autowired 自动装配 #### spring-05-anno 注解开发 #### spring-07-appconfig java配置spring #### spring-08-proxy 代理模式 - demo01 静态代理 - demo02 动态代理 #### spring-09-aop 切面 #### spring-10-mybatis 整合mybatis #### spring-12-transaction 声明式事务 ## Spring #### 简介 - Spring:春天->给软件行业的带来了春天 - 2002,首次推出了 Spring框架的雏形:interface21框架! - Spring框架即以interface21框架为基础,经过重新设计 ,并不断丰富其内涵,于2004年 3月24日发布了1.0正式版 - Rod Johnson 创始人,著名作者。 - Srring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架! - SSH:Struts2+Spring+Hibernate - SSM:SpringMVC+Spring+Mybatis - maven ```xml org.springframework spring-webmvc 5.3.9 org.springframework spring-jdbc 5.3.9 ``` #### 优点 - Spring是一个开源免费的框架(容器)! - Spring是一个轻量级的,非入侵式的框架! - 控制反转(IOC),面向前面编程(AOP)! - 支持事务的处理,对框架整合的支持! **总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面(AOP)编程的框架!** #### 组成 - Spring的7大模块 ![spring七大模块](./readme-img/spring七大模块.PNG) #### 拓展 - 现代化的java开发,就是基于Spring的开发 ![现代java开发](./readme-img/现代java开发.PNG) - Srpring Boot - 一个快速开发的脚手架 - 基于SpringBoot可以快速的开发单个微服务 - 约定大于配置! - Spring Cloud - SpringCloud是基于SpringBoot实现的 **弊端:发展了太久之后,违背了原来的理念!配置十分繁琐,人称:“配置地狱”** ## IOC理论推导 这种思想,从本质上解决了一个问题,我们程序猿不用再去管理对象的创建了。系统的耦合性大大降低~,可以更加专注在业务上。这是IOC的原型。 ## 第一个spring程序,hellospring 1. 创建com.test.pojo.Hello.java ```java package com.test.pojo; public class Hello { // private String str; public String getStr() { return str; } public void setStr(String str) { this.str = str; } @Override public String toString() { return "Hello{" + "str='" + str + '\'' + '}'; } } ``` 2. 在resources里面创建beans.xml[官方名称ApplicationContext.xml] ```xml ``` 3. 调用 ```java import com.test.pojo.Hello; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { // 获取spring的上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); // 我们的对象现在都在spring中管理了,我们要使用直接去里面取出来就可以了 Hello hello = (Hello)context.getBean("hello"); System.out.println(hello.toString()); } } ``` ## IOC创建对象的方式 #### 使用无参构造创建对象[默认] #### 使用有参构造创建对象 ```xml ``` #### 总结 在配置文件加载的时候,容器中管理的对象就已经初始化了! ## Spring配置 #### 别名 ```xml ``` #### bean的配置 ```xml ``` #### import ```xml ``` ## 依赖注入 #### 构造器方式注入 上面说的就是这个 #### set方式注入[重点] - 依赖注入:set注入! - 依赖:bean对象的创建,依赖于容器 - 注入:bean对象中的所有属性,由容器来注入 ```xml 红楼梦 西游记 三国演义 水浒传 听歌 看电影 玩游戏 LOL COC BOB 123456 ``` #### 扩展方式注入 - p命名空间注入 需要在xml头加入如下信息 ```xml xmlns:p="http://www.springframework.org/schema/p" ``` 使用 ```xml ``` - c命名空间注入 需要在xml头加入如下信息 ```xml xmlns:c="http://www.springframework.org/schema/c" ``` 使用 ```xml ``` ## Bean的作用域 #### 单例模式(Spring的默认机制) ```xml ``` #### 原型模式 ```xml ``` ## Bean的自动装配 #### 自动装配 是spring满足bean依赖的一种方式,spring在上下文中自动寻找,并自动给bean装配属性! - spring有三种装配的方式 1. 在xml中显示的配置 2. 在java中显示的配置 3. 隐式的自动装配bean【掌握】 ```xml ``` ```xml ``` 总结: - byName的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致! - byType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致! #### 注解自动装配 jdk1.5支持的注解,Spring2.5支持的注解。 使用注解须知: 1. 导入约束 ```xml xmlns:context="http://www.springframework.org/schema/context" ``` 2. 配置注解的支持 ```xml ``` 3. 直接在属性上使用即可!也可以在set方法上使用!【可以省略set方法,前提是在beans里面设置过值了】 @Nullable 标记了字段可以为null ```java package com.test.pojo; import org.springframework.beans.factory.annotation.Autowired; public class People { // 默认为true,如果显示的设置为false。说明这个对象可以为null,否则不允许为null @Autowired(required = false) @Qualifier(value="aaa") // 如果bean设置的id名字不和此处一致,可以显示的设置下其他的名字 @Resource(name="aaa") //这个也是可以实现自动转配的 private Cat cat; @Autowired private Dog dog; private String name; @Override public String toString() { return "People{" + "cat=" + cat + ", dog=" + dog + ", name='" + name + '\'' + '}'; } public Cat getCat() { return cat; } public Dog getDog() { return dog; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ``` @Autowired和@Resource的区别: 都是用来自动装配的,可以放在属性字段上 @Autowired通过byType的方式实现,而且必须要求这个对象存在!【常用】 @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的话就会报错【常用】 执行顺序不同:@Autowired通过byType的方式实现;@Resource默认通过byName的方式实现。 ## Spring注解开发 在Spring4之后,要使用注解开发,必须要保证aop包已经导入 使用注解需要导入context约束,增加注解的支持 1. bean 2. 属性如何注入 ```java package com.test.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; // 等价于 // @Component 组件 @Component public class User { @Value("小明") //赋值 相当于 public String name; } ``` 3. 衍生的注解 @Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层,它们的作用和@Component功能是一样的 - dao @Repository - service @Service - controller @Controller 4. 自动装配注解 - @Autowired:自动装配通过类型。名字。【如果@Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value="XXX")】 - @Nullable:字段标记了这个注解,说明这个字段可以为null - @Resource:自动装配通过名字。类型。 5. 作用域 - @Scope("singleton") 标注为单例模式 6. 小结 xml与注解: - xml更加万能,适用于任何场合!维护简单方便 - 注解不是自己类使用不了,维护相对复杂 xml与注解的最佳实践 - xml用来管理bean - 注解只负责完成属性的注入 - 我们在使用的过程中,只需要哦注意一个问题:必须让注解生效,就需要开启注解的支持 ## 使用Java的方式配置Spring JavaConfig是Spring的子项目,在Spring4之后,成为了一个核心功能。 - 创建个类,加入@Configuration注解就可以声明为配置类 ```java package com.test.config; import com.test.pojo.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration // 这个会被Spring容器脱管,注册到容器中,因为它本来就是一个@Component //@Configuration代表这个是一个配置类,就和我们之前看到的beans.xml是一样的 @ComponentScan("com.test.pojo") @Import(MyConfig2.class) //引入其他的配置类 public class MyConfig { @Bean //注册一个bean,就相当于之前写的一个bean标签,id是这个方法的名字,这个方法的返回值相当于bean标签的class属性 public User getUser(){ return new User(); //这个就是返回注入bean的对象 } } ``` - 实体类注解脱管 ```java package com.test.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class User { @Value("小明") //赋值 private String name; @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ``` - 测试类 ```java import com.test.config.MyConfig; import com.test.pojo.User; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MyTest { public static void main(String[] args) { //如果完全使用了配置类方式,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载! ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); User user = context.getBean("getUser", User.class); System.out.println(user.getName()); } } ``` 这种纯java配置,在SpringBoot种随处可见。 ## 代理模式 为什么要学习代理模式?因为这是SpringAOP的底层! 代理模式的好处: 1. 可使真实的角色的操作更加纯粹,不用去关注一些共用的业务。 2. 公共业务就交给了代理角色!实现了业务的分工 3. 公共业务发生扩展的时候,方便集中管理 缺点: 1. 一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率会变低~ 代理模式的分类: - 静态代理 - 抽象角色:一般会使用接口或抽象类来解决 - 真实角色:被代理的角色 - 代理角色:代理真实角色后,会做一些附属操作 - 客户:访问代理对象的人! 代码:模拟中介帮房东租房 1. 接口 ```java package com.test.demo01; // 租房接口 public interface Rent { public void rent(); //出租房屋 } ``` 2. 真实角色 ```java package com.test.demo01; // 房东 public class Host implements Rent { public void rent() { // System.out.println("房东要出租房子"); } } ``` 3. 代理角色 ```java package com.test.demo01; // 代理中介 public class Proxy implements Rent { private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } public void rent() { // seeHose(); //看房 host.rent(); fare(); } //看房,属于附加的操作,可以看多个房子 public void seeHose(){} // 收中介费 public void fare(){} } ``` 4. 客户端访问代理角色 ```java package com.test.demo01; public class Client { public static void main(String[] args) { Host host = new Host(); // 代理,代理角色有一个附属操作 Proxy proxy = new Proxy(host); proxy.rent(); } } ``` - 动态代理 1. 动态代理和静态代理角色一样 2. 动态代理的代理类是动态生成的,不是我们直接写好的 2. 动态代理分为两大类:基于接口的动态代理,基于类的的动态代理 - 基于接口 ------- JDK动态代理; 需要了解两个类:Proxy代理,InvocationHandler调用处理程序,代码见 **spring-08-proxy**的demo2代码 - 基于类:cglib - java字节码实现:javassist ## AOP - spring使用aop需要导入一个包 ```xml org.aspectj aspectjweaver 1.9.4 ``` 方式一:使用Spring的API接口 1. bean的配置 ```xml xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> ``` 2. 测试类 ```java import com.test.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 动态代理代理的是接口 UserService userService = (UserService) context.getBean("userService"); userService.add(); } } ``` 方式二:自定义类来实现 1. bean的配置 ```xml ``` 2. 自定义类 ```java package com.test.diy; public class DiyPointCut { public void before(){ System.out.println("方法执行前"); } public void after(){ System.out.println("方法执行后"); } } ``` 3. 测试类 ```java import com.test.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 动态代理代理的是接口 UserService userService = (UserService) context.getBean("userService"); userService.add(); } } ``` 方式三:注解方式实现 1. 配置文件 ```xml ``` 2. 注解类 ```java package com.test.diy; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; // 使用注解方式实现aop @Aspect public class AnnotationPointCut { @Before("execution(* com.test.service.UserServiceImpl.*(..))") public void before(){ System.out.println("方法执行前"); } @After("execution(* com.test.service.UserServiceImpl.*(..))") public void after(){ System.out.println("方法执行后"); } } ``` 3. 测试类 ```java import com.test.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 动态代理代理的是接口 UserService userService = (UserService) context.getBean("userService"); userService.add(); } } ``` ## 整合Mybatis 步骤: 1. 导入相关jar包 - junit - mybatis - mysql - spring - aop - mybatis-spring【new】 ```xml mysql mysql-connector-java 5.1.47 org.mybatis mybatis 3.5.2 org.springframework spring-jdbc 5.3.9 org.springframework spring-webmvc 5.3.9 junit junit 4.12 org.aspectj aspectjweaver 1.9.4 org.mybatis mybatis-spring 2.0.6 ``` 2. 编写配置文件 ```xml ``` 3. 测试 ## 声明式事务 #### propagation 传播特性 七种 ## 附录 #### 注解说明 - @Autowired:自动装配通过类型。名字。【如果@Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value="XXX")】 - @Nullable:字段标记了这个注解,说明这个字段可以为null - @Resource:自动装配通过名字。类型。 - @Component:组件,放在类上,说明这个类被Spring管理了,就是bean!