# 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大模块

#### 拓展
- 现代化的java开发,就是基于Spring的开发

- 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!