# 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的作用域** ![1586093707060](C:\Users\QHQ\AppData\Roaming\Typora\typora-user-images\1586093707060.png) 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(); } ``` 整合 方法一: ![1586177510119](C:\Users\QHQ\AppData\Roaming\Typora\typora-user-images\1586177510119.png) 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); } } ```