# Spring-Study
**Repository Path**: zuojianhao/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-08-15
- **Last Updated**: 2021-08-15
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Spring-Study
[Kuang shen Spring study in bilibili](https://www.bilibili.com/video/BV1WE411d7Dv?p=1)
## 1. 简介
spring理念:是现有的技术更加容易使用,本身是一个大杂烩。
- SSH:Struct2 + Spring + Hibernate
- SSM: SpringMVC + Spring + Mybatis
官网: https://spring.io/projects/spring-framework#overview
官方下载: https://repo.spring.io/release/org/springframework/spring/
GitHub: https://github.com/spring-projects/spring-framework
[Spring Web MVC](https://mvnrepository.com/artifact/org.springframework/spring-webmvc) **»** [5.2.5.RELEASE](https://mvnrepository.com/artifact/org.springframework/spring-webmvc/5.2.5.RELEASE)
```xml
org.springframework
spring-webmvc
5.2.5.RELEASE
org.springframework
spring-jdbc
5.2.3.RELEASE
```
- spring是开源的免费的容器。
- spring是一个轻量级的,非入侵式的。
- 控制反转(IOC),面向切面编程 (AOP)。
- 支持事务处理,对框架整合的支持。
总结:spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架。
## 2.IOC理论
1. UserDao
2. UserDaoImp
3. UserSevice
4. UserServiceImp
在之前,用户的需求可能会影响原来的代码。
使用一个set。
```java
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
```
- 之前是主动创建对象,控制权在程序员手上。
- 使用set之后,是被动接受对象。
## 3. Hello Spring
pojo中
```java
package com.hou.pojo;
public class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
'}';
}
}
```
resource种
```xml
```
test
```java
import com.hou.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());
}
}
```
bean = 对象
id = 变量名
class = new的对象
property 相当于给对象中的属性设值
核心用set注入
第一个文件中
```xml
```
## 4. IOC创建对象的方式
1. 使用无参构造创建对象,默认。
2. 使用有参构造
下标赋值
```xml
```
类型赋值(不建议使用)
```xml
```
直接通过参数名
```xml
```
Spring类似于婚介网站!
你想不想要,对象都在里面。注册bean之后用不用被实例化。
## 5. Spring配置
**别名**
```xml
```
**Bean的配置**
- id:bean的id标识符
- class:bean对象所对应的类型
- name:别名,更高级,可以同时取多个别名。
**import**
一般用于团队开发,它可以将多个配置文件,导入合并为一个
```xml
```
## 6. DI依赖注入
**构造器注入**
**set方式注入**(重点)
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器来注入
【环境搭建】
1. 复杂类型
2. 真实测试对象
```java
package com.pojo;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] books;
private List hobbies;
private Map card;
private Set game;
private Properties infor;
private String wife;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbies=" + hobbies +
", card=" + card +
", game=" + game +
", infor=" + infor +
", wife='" + wife + '\'' +
'}';
}
}
```
```java
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
```
```xml
三国
西游
水浒
eat
drink
play
wangzhe
daota
lol
20200405
hdk
```
**第三方**
p标签和c标签
```java
package com.pojo;
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
```
```xml
```
**bean的作用域**

1. 单例模式(默认)
```xml
```
2. 原型模式: 每次从容器中get的时候,都产生一个新对象!
```xml
```
3. 其余的request、session、application这些只能在web开放中使用!
## 7. Bean的自动装配
- 自动装配是Spring是满足bean依赖的一种方式
- Spring会在上下文自动寻找,并自动给bean装配属性
-
在Spring中有三种装配的方式
1. 在xml中显示配置
2. 在java中显示配置
3. 隐式的自动装配bean 【重要】
1. 环境搭建:一个人有两个宠物
2. Byname自动装配:byname会自动查找,和自己对象set对应的值对应的id
保证所有id唯一,并且和set注入的值一致
3. Bytype自动装配:byType会自动查找,和自己对象属性相同的bean
保证所有的class唯一
```java
public class Cat {
public void jiao(){
System.out.println("miao");
}
}
```
````java
public class Dog {
public void jiao(){
System.out.println("wow");
}
}
````
```java
package com.pojo;
public class People {
private Cat cat;
private Dog dog;
private String name;
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```
```xml
```
**使用注解自动装配**
jdk1.5支持的注解,spring2.5支持的注解
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.
导入context约束
```xml
```
@Autowire
在属性上个使用,也可以在set上使用
我们可以不用编写set方法了
```java
public class People {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
}
```
```xml
@Nullable 字段标志的注解,说明这个字段可以为null
```
如果@Autowired自动装配环境比较复杂。自动装配无法通过一个注解完成的时候
我们可以使用@Qualifier(value = "dog")去配合使用,指定一个唯一的id对象
```java
public class People {
@Autowired
private Cat cat;
@Autowired
@Qualifier(value = "dog")
private Dog dog;
private String name;
}
```
@Resource(name="dog")也可以
区别:
- @autowire通过byType实现,而且必须要求这个对象存在
- @resource默认通过byName实现,如果找不到,通过byType实现
## 8. 使用注解开发
在spring4之后,必须要保证aop的包导入
使用注解需要导入contex的约束
```xml
```
1. 属性如何注入
```java
@Component
public class User {
@Value("dong")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```
2. 衍生的注解
@Component有几个衍生注解,会按照web开发中,mvc架构中分层。
- dao (@Repository)
- service(@Service)
- controller(@Controller)
这四个注解功能一样的,都是代表将某个类注册到容器中
3. 作用域
@Scope("singleton")
```java
@Component
@Scope("prototype")
public class User {
@Value("dong")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```
小结:
xml与注解
- xml更加万能,维护简单
- 注解,不是自己的类,使用不了,维护复杂
最佳实践:
- xml用来管理bean
- 注解只用来完成属性的注入
```xml
```
## 9. 使用java方式配置spring
JavaConfig
Spring的一个子项目,在spring4之后,,他成为了核心功能
```java
@Configuration //这个也会被spring容器托管,注册到容器中,因为他本来就是一个@Component
@ComponentScan("com.pojo")
@Import(Config2.class)
public class MyConfig {
@Bean
public User getUser(){
return new User();
}
}
```
```java
@Component
public class User {
@Value("dong")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
```
这种纯java配置方式
在springboot中,随处可见
## 10. 动态代理
动态代理和静态代理
角色一样
动态代理类是动态生成的,不是我们直接写好的!
动态代理:基于接口,基于类
- 基于接口:JDK的动态代理【使用】
- 基于类:cglib
- java字节码
InvocationHandler
Proxy
```java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//会这个类,自动生成代理类
public class ProxyInvocation implements InvocationHandler {
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
Object result = method.invoke(rent, args);
fare();
return result;
}
public void seeHouse(){
System.out.println("see house");
}
public void fare(){
System.out.println("fare");
}
}
```
```java
public interface Rent {
void rent();
}
```
```java
public class Host implements Rent {
public void rent() {
System.out.println("host rent");
}
}
```
```java
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色
ProxyInvocation proxyInvocation = new ProxyInvocation();
//通过调用程序处理角色来处理我们要调用的接口对象
proxyInvocation.setRent(host);
Rent proxy = (Rent) proxyInvocation.getProxy(); //这里的proxy是动态生成的
proxy.rent();
}
}
```
## 11.AOP
```xml
org.aspectj
aspectjweaver
1.9.4
```
方法一:使用spring接口【springAPI接口实现】
```xml
```
```java
public class UserServiceImp implements UserService {
public void add() {
System.out.println("add");
}
public void delete() {
System.out.println("delete");
}
public void query() {
System.out.println("query");
}
public void update() {
System.out.println("update");
}
}
```
```java
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
//method:要执行的目标对象的方法
//args:参数
//target:目标对象
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+method.getName());
}
}
```
```java
public class AfterLog implements AfterReturningAdvice {
//returnVaule: 返回值
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(method.getName()+returnValue);
}
}
```
```java
public class Mytest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplcationContext.xml");
//动态代理代理的是接口
UserService userService = (UserService) context.getBean("userservice");
userService.add();
}
}
```
方法二:自定义来实现AOP【主要是切面定义】
```xml
```
```java
public class DiyPointcut {
public void before(){
System.out.println("before");
}
public void after(){
System.out.println("after");
}
}
```
方法三:注解方式
```xml
```
```java
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect //标注这个类是一个切面
public class Annotation {
@Before("execution(* com.service.UserServiceImp.*(..))")
public void before(){
System.out.println("before");
}
@After("execution(* com.service.UserServiceImp.*(..))")
public void after(){
System.out.println("after");
}
//在环绕增强中,我们可以给地暖管一个参数,代表我们要获取切入的点
@Around("execution(* com.service.UserServiceImp.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("around");
Object proceed = joinPoint.proceed();
System.out.println("after around");
}
}
```
## 12. 整合mybatis
文档: https://mybatis.org/spring/zh/
```xml
spring-study
com.hou
1.0-SNAPSHOT
4.0.0
spring-10-mybatis
mysql
mysql-connector-java
5.1.47
org.mybatis
mybatis-spring
2.0.4
org.springframework
spring-jdbc
5.2.3.RELEASE
org.mybatis
mybatis
3.5.2
org.aspectj
aspectjweaver
1.9.4
org.projectlombok
lombok
1.18.12
src/main/resources
**/*.properties
**/*.xml
src/main/java
**/*.properties
**/*.xml
true
```
```xml
```
```xml
```
```java
public interface UserMapper {
List selectUser();
}
```
整合
方法一:

UserMapperImpl
```java
package com.mapper;
import com.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSessionTemplate;
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public List selectUser() {
UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
```
mybatis.xml
```xml
```
spring.xml
```xml
```
test
```java
import com.mapper.UserMapper;
import com.pojo.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
public class Mytest {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
for (User user : userMapper.selectUser()) {
System.out.println(user);
}
}
}
```
方法二:
```xml
```
```java
package com.mapper;
import com.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperIml2 extends SqlSessionDaoSupport implements UserMapper {
public List selectUser() {
SqlSession sqlSession = getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
```
## 13. 声明式事务
- 要么都成功,要么都失败
- 十分重要,涉及到数据一致性
- 确保完整性和一致性
事务的acid原则:
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会被影响。
Spring中的事务管理
- 声明式事务
- 编程式事务
声明式事务
```xml
```
```xml
```
Mapper
```java
package com.mapper;
import com.pojo.User;
import java.util.List;
public interface UserMapper {
List selectUser();
int addUser(User user);
int delete(int id);
}
```
```xml
insert into mybatis.user (id, name, pwd) values
(#{id}, #{name}, #{pwd})
delete from mybatis.user where id=#{id}
```
```java
package com.mapper;
import com.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperIml2 extends SqlSessionDaoSupport implements UserMapper {
public List selectUser() {
User user = new User(6, "long", "zhi");
SqlSession sqlSession = getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.addUser(user);
mapper.delete(6);
return mapper.selectUser();
}
public int addUser(User user) {
return getSqlSession().getMapper(UserMapper.class).addUser(user);
}
public int delete(int id) {
return getSqlSession().getMapper(UserMapper.class).delete(id);
}
}
```