# SpringStudy
**Repository Path**: chmingx/spring-study
## Basic Information
- **Project Name**: SpringStudy
- **Description**: 学习Spring
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-05-18
- **Last Updated**: 2022-03-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Spring
[TOC]
ssm = springmvc + spring + mybatis
```xml
org.springframework
spring-webmvc
5.3.6
org.springframework
spring-jdbc
5.3.6
```
优点:
- 开源免费
- 轻量级,非入侵式框架
- 控制反转IOC
- 面向切面编程AOP
- 支持事务,对框架整合支持
组成:
- AOP
- ORM
- DAO
- Web
- Context
- MVC
- Core
Spring Boot 快速开发的脚手架,基于springboot可以快速开发单个微服务
Spring Cloud 基于Spring Boot实现的,集成的微服务
## 1 IOC理论推导
```java
private UserDao userDao;
// 通过set方法进行依赖注入,实现控制反转
// 之前,程序主动创建对象,控制权在程序员手中;现在主动性在用户手上,程序被动接收对象
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
```
==控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式. 在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入==
控制:由Spring创建对象,而不是程序本身;属性也由Spring设置
反转:程序本身不创建对象,被动接收对象
依赖注入:利用set方法进行注入
IOC: 一言以蔽之,对象由Spring来创建、管理、装配
什么事IOC:
> 控制反转:把对象创建和对象之间的调用过程,交给Spring进行管理。能够降低耦合度
IOC底层原理:
> xml解析、工厂模式、反射
### 1.1 IOC 创建对象
1. 默认使用无参构造
```xml
```
2. 有参构造
```xml
```
## 2 依赖注入
依赖:bean对象的创建依赖于容器
注入:bean对象的属性由容器来注入
### 2.1 构造器注入
```xml
```
### 2.2 set注入
```xml
```
### 2.3 扩展方式注入, C/P命名空间
```xml
```
### 2.4 特殊属性注入
```xml
红楼梦
西游记
水浒传
三国演义
music
movie
reading
LOL
King
20200101001
male
foobar
```
## 3 Bean的作用域Scope
- singleton 单例,对象是单一的,只有一个,默认
- prototype 原型,每次从容器中获取时都拿到一个新的对象,只不过属性与前面一致
```xml
```
## 4 Bean的自动装配
- 手动装配:
- 在xml中显示的配置(见上面)
- 自动装配:
- 在xml中实现
- byName
- byType
- 在java中显示配置,通过注解
- @Autowired
- @Resource
### 4.1 xml中实现自动装配
```xml
```
```xml
```
### 4.2 在Java中通过注解实现
#### 4.2.1 @Autowired
```xml
```
- @Autowired, 自动装配,在属性或set方法上使用,可以不用编写set方法
- required
- @Nullable, 可以为空,
- @Qualifier, 指定bean对象进行注入
```java
public class Person {
private String name;
// 如果显示标注了required为false,则这个属性可以为空
@Autowired(required = false)
private Cat cat;
@Autowired
@Qualifier("dog") // 指定名称,用于处理变量名与属性名不一致的情况
private Dog dog;
@Nullable
private String name; // name可以为空
}
```
#### 4.2.2 @Resource
- Resource, 自动装配,会先匹配名称,再匹配类型
```java
public class Person {
private String name;
// java自带注解
@Resource
private Cat cat;
@Resource(name="dog")
private Dog dog;
}
```
## 5 使用注解开发
不需要再xml中编写bean了,直接注解生成bean
```xml
```
- @Component, 这个类被Spring管理了,用于类
- @Repository/@Mapper, Component的引申注解,效果等同于Component, 通常用于Spring的DAO
- @Service
- @Controller
- @Value, 为属性添加默认值, 用于属性或set方法
- @Scope, 为类设置作用域,@Scope("singleton"), 设置为单例, 等同于在 `beans.xml`中设置 ``
- singleton
- prototype
```java
// @Component注解等价于 , 就是说在容器中注入这样一个对象
@Component
@Scope("singleton")
public class User {
@Value("foobar") // 等价于
private String name;
@Autowired
private Cat cat;
}
```
一般,用xml管理bean,用注解注入属性
## 6 使用Java进行配置
xml都不用了, 直接再Java中进行配置
```java
public class User {
@Value("foobar")
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
@Configuration
public class AppConfig {
//
// 方法名相当于bean中的id
// 返回值类型相当于bean中的class
@Bean
public User user() {
return new User();
}
}
```
AppConfig等同于下面的xml
```xml
```
```java
public class UserTest {
@Test
public void test() {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
User user = context.getBean("user", User.class);
System.out.println(user);
}
}
```
## 7 代理模式
扩展被代理对象的功能
- 静态代理
- 动态代理
### 7.1 静态代理
```java
// 抽象成员
interface BuyHouse{
public void buy();
}
```
```java
// 被代理对像
class BuyHouseImpl implement BuyHouse{
@Override
public void buy(){
System.out.println("buy a house");
}
}
```
```java
// 代理对象
class BuyHouseProxy implement BuyHouse{
private BuyHouse buyHouse;
public BuyHouseProxy(BuyHouse buyHouse){
this.buyHouse = buyHouse;
}
@Override
public void buy(){
System.out.println("看房");
buyHouse.buy();
System.out.println("收中介费");
}
}
```
```java
// 客户端
class Client{
public static void main(String[] args){
BuyHouse buyHouse = new BuyHouseImpl();
BuyHouseProxy proxy = new BuyHouseProxy(buyHouse);
proxy.buy();
}
}
```
### 7.2 动态代理
Proxy: 生成动态代理
InvocationHandler: 调用处理程序并返回结果
```java
public interface BuyHouse {
public void buy();
}
```
```java
package org.example.dynamic;
public class BuyHouseImpl implements BuyHouse{
@Override
public void buy() {
System.out.println("buy house");
}
}
```
```java
package org.example.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理调用处理器
*/
public class DynamicProxyHandler implements InvocationHandler {
// 被代理的接口
private Object object;
public DynamicProxyHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Begin-----------------");
Object invoke = method.invoke(object, args); // 利用反射调用类里面的方法
System.out.println("After-----------------");
return invoke; // invoke 为调用结果,如果没有则为null
}
}
```
```java
package org.example.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
BuyHouse buyHouse = new BuyHouseImpl();
// 创建调用处理器
InvocationHandler invocationHandler = new DynamicProxyHandler(buyHouse);
// 动态创建代理对象
BuyHouse proxyInstance = (BuyHouse) Proxy.newProxyInstance(
invocationHandler.getClass().getClassLoader(), // 代理类的类加载器
buyHouse.getClass().getInterfaces(), // 被代理类的接口
invocationHandler // 代理调用处理器
);
proxyInstance.buy();
}
}
```
## 8 AOP 面向切面编程

本质是动态代理
```xml
org.aspectj
aspectjweaver
1.9.4
```
### 8.1 使用Spring的切片API来实现切片
- 编写切面
```java
public class BeforeLog implements MethodBeforeAdvice {
/**
*
* @param method 要执行的目标对象,或被代理对象的方法
* @param objects 参数
* @param o 目标对象
* @throws Throwable
*/
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("执行" + method.getName() + " ...");
}
}
```
```java
public class AfterLog implements AfterReturningAdvice {
/**
*
* @param o 方法返回值
* @param method 要执行的目标对象,或被代理对象的方法
* @param objects 参数
* @param o1 目标对象
* @throws Throwable
*/
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println(method.getName() + "结束,结果为:" + o);
}
}
```
- 定义切入点,进行切入
```xml
```
- 测试
```java
public class UserServiceTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.select();
}
}
```
### 8.2 自定义类实现切片
- 使用自定义切片
```java
package org.example.diyPointCut;
// 自定义切片类
public class DIYPointCut {
public void before() {
System.out.println("before ...");
}
public void after() {
System.out.println("after ...");
}
}
```
- 定义切入点,进行切入
```xml
```
### 8.3 使用注解实现切片
- 使用注解实现切片
```java
package org.example.diyPointCut;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnotationPointCut {
@Before("execution(* org.example.service.UserServiceImpl.*(..))")
public void before() {
System.out.println("=======before==============");
}
@After("execution(* org.example.service.UserServiceImpl.*(..))")
public void after() {
System.out.println("=======after==============");
}
// 在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
@Around("execution(* org.example.service.UserServiceImpl.*(..))")
public void aroud(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前...");
Signature signature = joinPoint.getSignature();
System.out.println("signature:" + signature);
Object proceed = joinPoint.proceed();
System.out.println("环绕后...");
}
}
```
```xml
```
### 8.4 切点表达式
Advice主要类型:
- @Before
- @After
- @AfterReturning
- @AfterThrowing
- @Around
- @Pointcut 设置切入点
```java
//设置切点为delete方法
@Pointcut(value = "execution(* com.maoge.demo1.User.delete(..))")
private void myPointcut()
{}
@Before(value = "myPointcut()")
public void UserCheck1()
{
System.out.println("用户校验1");
}
@AfterThrowing(value = "myPointcut()")
public void UserCheck2()
{
System.out.println("用户校验2");
}
@AfterReturning(value = "myPointcut()")
public void UserCheck3()
{
System.out.println("用户校验3");
}
```
PCD:pointcut designators
- within 筛选出某包下的所有类
- execution execution(注解?修饰符?返回值类型 类型声明?方法名(参数)异常?)
- @within表示匹配带有指定注解的类
- @annotation 匹配有指定注解的方法(注解作用在方法上面)
```java
execution(修饰符匹配式? 返回类型匹配式 类名匹配式? 方法名匹配式(参数匹配式) 异常匹配式?)
execution(* com.xyz.service..*.*(..)): 匹配com.xyz.service及其子包下的任意方法
within(com.xyz.service.*)com.xyz.service包下的类,不包括子包
@within(com.spring.annotation.BusinessAspect)
```
PCD之间支持,`&& || !`三种运算符。上文示例中就使用了&& 运算符。`||`表示或(不是短路或)。`!`表示非。
## 9 整合mybatis
- 导入依赖
```xml
org.mybatis
mybatis-spring
2.0.2
```
- 编写spring-dao.xml配置, 使用Spring的DataSource替换Mybatis配置
```xml
```
```xml
```
- 在spring-dao中配置SqlSessionFactory
```xml
```
- 编写接口及实现类
```java
package org.example.mapper;
import org.apache.ibatis.annotations.Param;
import org.example.pojo.User;
public interface UserMapper {
User getUserById(@Param("id") int id);
}
```
```java
package org.example.dao;
import org.example.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSessionTemplate;
@Override
public User getUserById(int id) {
UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
return userMapper.getUserById(id);
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
}
```
- 编写mapper.xml
```xml
```
- 添加SqlSessionTemplate, 注入SqlSessionFactory生产SqlSessionTemplate
```xml
```
- 注入SqlSessionTemplate生产Mapper
```xml
```
- 测试
```java
public class UserMapperTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
System.out.println(userMapper.getUserById(2));
}
}
```
方法二,不在配置中显示生成SqlSessionTemplate,使用SqlSessionDaoSupport
- 实现类需继承SqlSessionDaoSupport
```java
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
@Override
public User getUserById(int id) {
return getSqlSession().getMapper(UserMapper.class).getUserById(id);
}
}
```
- 配置UserMapper的bean
```xml
```
- 测试
```java
public class UserMapperTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
System.out.println(userMapper.getUserById(2));
}
}
```
## 10 事务
ACID: 原子性、一致性、隔离性、持久性
Spring中事务:
- [x] 声明式事务:交给容器管理事务,是AOP
- [ ] 编程式事务:需要在代码中进行事务管理
### 10.1 声明式事务
- 配置声明式事务
```xml
```
- 导入约束
```xml
```
- 结合AOP实现事务的织入
```xml
```
- 配置事务切入
```xml
```
- 测试
```java
@Test
public void testTransaction() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
for (User user : userMapper.getAllUser()) {
System.out.println(user);
}
userMapper.addUser(new User(3, "ww", "456789"));
userMapper.deleteUser(4);
for (User user : userMapper.getAllUser()) {
System.out.println(user);
}
}
```
## 11 MVC
MVC是模型视图控制器的简写,是将业务逻辑、数据、显示分离的方法来组织代码。能降低试图与业务逻辑间的双向耦合
SpringMVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架, 就是servlet
- 轻量级
- 高效
- 与Spring无缝结合
- 约定优于配置
- 功能强大RESTful,数据验证,本地化,格式化
SpringMVC围绕DispatherServlet设计。DispatherServlet的作用是将请求分别发送到不同处理器
## 12 Json
json是JavaScript对象的字符串表示法,它使用文本表示一个JavaScript对象,本质是一个字符串
```javascript
var obj = {a: 'Hello', b: 100}
var json = '{"a": "Hello", "b": 100}'
```
```xml
com.fasterxml.jackson.core
jackson-databind
2.10.0
com.alibaba
fastjson
1.2.60
```