学习内容是跟着b站大佬遇见狂神说学习的,大家有兴趣建议去关注学习。
1.Spring
1.1 简介Spring
Spring: 简化企业开发的复杂性,使现有技术更加容易使用,比如Servlet
官网:https://spring.io/projects/spring-framework#overview
官网下载地址:https://repo.spring.io/release/org/springframework/spring/
GitHub:https://github.com/spring-projects/spring-framework
org.springframework spring-webmvc 6.0.9
org.springframework spring-jdbc 6.0.9
1.2 优点
Spring是一个开源的免费的框架(容器)
Spring使一个轻量级的、非入侵的框架
控制反转(IOC)、面向切面编程(AOP)
支持事务的处理,对框架整合的支持
总结:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
1.3 组成
1.4 拓展
现代化的Java开发,就是基于Spring的开发。
- Spring Boot
- 一个快速开发的脚手架
- 基于SpringBoot可以快速开发单个微服务
- 约定大于配置,和maven一样
- Spring Cloud
- Spring Cloud是基于SpringBoot实现
现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提需要掌握Spring和SpringMVC。
弊端:发展太久之后,违背原有的理念,配置十分繁琐。
2.IOC理论推导
1.UserDao接口
2.UserDaoImpl实现类
3.UserService业务接口
4.UserServiceImpl业务实现类
在之前的业务中,用户的需求可能会影响我们原来的代码,需要根据用户的需求去修改源代码,如果程序代码量十分大,修改一次成本会很贵!
我们使用一个Set接口实现类
private UserDao userdao;
//利用set实现动态值的注入
public void setUserdao(UserDao userdao) {
this.userdao = userdao;
}
public void getUser(){
userdao.getUser();
}
- 之前程序是主动创建对象,控制权在程序员手上
- 使用了Set后,程序不再拥有主动权,而是变成了被动的接收对象!
这种思想从本质上解决了问题,程序员buoy那个再去管理对象的创建了,系统的耦合性大大降低,可以更加关注在业务的实现上。
3.HelloSpring
-
Hello对象是谁创建的
hello对象是由Spring创建的 -
Hello对象的属性是怎么设置的
由Spring容器设置
这个过程就是控制反转
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的。
反转:程序本身不创建对象,而是变成被动的接受对象。
依赖注入:就是利用set方法注入的
IOC是一种编程思想,由主动的编程变成被动的接受。
可以通过newClassPathXmlApplicationContext去浏览一下底层源码。
目前不需要在程序中去改动了,要实现不同的操作吗,只需要在xml配置文件中进行修改,所谓的IOC,就是用Spring来创建、管理和装配。
4.IOC创建对象的方式
- 1.使用无参构造创建对象,默认
- 2.假设我们要使用有参构造创建对象
- 下标赋值
<bean id="user" class="com.baidu.pojo.User">
<constructor-arg index="0" value="狂神说Java"/>
</bean>
- 类型创建
<bean id="user" class="com.baidu.pojo.User">
<constructor-arg type="java.lang.String" value="lihan"/>
</bean>
- 参数名
<bean id="user" class="com.baidu.pojo.User">
<constructor-arg name="name" value="lihan"/>
</bean>
在配置文件加载的时候,容器中管理的对象就已经初始化了
5.Spring配置
5.1 别名
<!-- 别名,如果添加了别名,就可以使用别名来获取这个对象-->
<alias name="user" alias="userNew"/>
<!-- -->
5.2 Bean的配置
<!-- id:bean的唯一标识符,也就是相当于对象名
class:bean对象所对应的全限定名:包名+类型
name:也是别名,而且name也可以取多个别名
-->
<bean id="userT" class="com.baidu.pojo.UserT" name="user2 u2,u3,u4">
<property name="name" value="baidu"/>
</bean>
5.2 import
一般适用于团队开发,可以将多个配置文件导入合并为一个
假设,现有项目中有多个人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,可以利用import将所有人的beans.xml合并为一个总的。
- 张三
- 李四
- 王五
- applicationContext.xml
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml">
使用的时候直接用总的配置就可以了
6.依赖注入
6.1 构造器注入
看前
6.2 Set注入(重点)
- 依赖注入:Set注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的属性,由容器来注入
环境搭建:
1.复杂类型
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
2.真实测试对象
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
}
3.bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--第一种,普通值注入,value-->
<bean id="student" class="com.baidu.pojo.Student">
<property name="name" value="lihan"/>
</bean>
</beans>
4.测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
}
5.完善注册信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.baidu.pojo.Address">
<property name="address" value="吉林"/>
</bean>
<bean id="student" class="com.baidu.pojo.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="lihan"/>
<!--第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!--数组-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>三国演义</value>
<value>水浒传</value>
</array>
</property>
<!--List-->
<property name="hobbies">
<list>
<value>抽烟</value>
<value>喝酒</value>
<value>烫头</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="身份证" value="412721199805161434"/>
<entry key="银行卡" value="6217002430044188986"/>
</map>
</property>
<!--Set-->
<property name="games">
<set>
<value>lol</value>
<value>coc</value>
<value>bob</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--Properties-->
<property name="info">
<props>
<prop key="学号">202108034</prop>
<prop key="姓名">李涵</prop>
</props>
</property>
</bean>
</beans>
6.3 拓展方式注入
我们可以使用p和c命名空间注入
使用:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--p命名空间,可以直接注入属性的值:property-->
<bean id="user" class="com.baidu.pojo.User" p:name="李涵" p:age="25"/>
<!--c命名空间,通过构造器注入:construct-args-->
<bean id="user2" class="com.baidu.pojo.User" c:age="25" c:name="李涵"/>
</beans>
测试:
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user2", User.class);
System.out.println(user);
}
注意点:p和c不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
6.4 bean的作用域
- 单例模式(Spring默认机制)
<bean id="user2" class="com.baidu.pojo.User" c:age="25" c:name="李涵" scope="singleton"/>
- 原型模式:每次从容器get的时候。都会产生一个新对象
<bean id="user2" class="com.baidu.pojo.User" c:age="25" c:name="李涵" scope="prototype"/>
- 其余的request、session、application这些只能在web开发中使用。
7.Bean的自动装配
- 自动装配是Spring满足bean依赖的一种方式。
- Spring会在上下文中自动寻找,并自动给bean装配属性。
在Spring中有三种装配的方式
- 在xml中显式的配置
- 在Java中显式的配置
- 隐式的自动装配bean(重要)
7.1 测试
环境搭建
7.2 ByName自动装配
<!--byName:会自动在容器上下文中查找,和自己对象set方法对应的值的bean id-->
<bean id="people" class="com.baidu.pojo.People" autowire="byName">
7.3 ByType自动装配
<!--byType:会自动在容器上下文中查找,和自己对象属性相同的bean -->
<bean id="people" class="com.baidu.pojo.People" autowire="byType">
小结
- ByName:需要保证所有bean的id唯一,并且这恶鬼bean需要和自动注入的属性的set方法的值一致
- ByType:需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
7.4 使用注解实现自动装配
1.导入约束:context约束
2.配置注解的支持:context:annotation-config
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
直接在属性上使用即可,也可以在set方法使用。
使用Autowired就可以不用编写Set方法,前提是自动装配的属性在IOC(Spring)容器中存在,且符合ByType。
@Resource注解
小结:@Resource和@Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired通过ByType方式实现,而且必须要求这个对象存在!(常用)
- @Resource默认通过ByName方式实现,如果找不到,则通过ByType实现,否则就报错!(常用)
- 执行顺序不同:@Autowired 通过ByType的方式实现。@Resource默认通过ByName实现
8.使用注解开发
在Spring4之后,要使用注解开发,必须保证aop包的导入。
使用注解需要导入context约束,增加注解的支持。
- bean
2.属性注入
@Component
public class User {
@Value("李涵")
public String name;
// 等价于<property name="name" value="李涵"/>
public void setName(String name){
this.name = name;
}
}
- 衍生的注解
@Component有几个衍生注解,在web开发中,会按照mvc三层架构分层
- dao:【@Repository】
- service:【@Service】
- controller:【@Controller】
这四个注解功能一样,都是代表将某个类注册到Spring中,装配Bean - 自动装配
@Autowired:自动装配通过类型、名字,如果Autowired不能唯一自动装配属性,则需要通过@Qualifier(value="xxx")
@Nullable: 字段标记了这个注解,说明这个字段可以未null
@Resource:自动装配通过名字、类型
- 作用域
@Component
@Scope("prototype")
public class User {
@Value("李涵")
public String name;
// 等价于<property name="name" value="李涵"/>
public void setName(String name){
this.name = name;
}
}
-
小结
xml和注解:- xml更加万能,适用于任何场合,维护简单方便
- 注解不是自己类使用不了,维护相当复杂
xml与注解最佳实践:
- xml用来管理bean
- 注解只负责完成属性的注入
- 在使用的过程中,只需要注意一个问题,必须让注解生效,就需要开启注解的支持
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.baidu.pojo"/>
<context:annotation-config/>
9.使用Java的方式配置Spring
10.代理模式
10.1静态代理
角色分析:
- 抽象角色:一般会使用接口或抽象类来实现
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人
代理步骤:
1.接口
//租房
public interface Rent {
public void rent();
}
2.真实角色
//房东
public class Host implements Rent{
public void rent(){
System.out.println("房东要出租房子");
}
}
3.代理角色
public class Porxy implements Rent{
private Host host;
public Porxy() {
}
public Porxy(Host host) {
this.host = host;
}
public void rent(){
seehouse();
fare();
host.rent();
}
//看房
public void seehouse(){
System.out.println("中介带你看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
4.客户端访问代理角色
public class Client {
public static void main(String[] args) {
//房东要出租房子
Host host = new Host();
//代理
Porxy proxy = new Porxy(host);
proxy.rent();
}
}
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共交给代理角色,实现业务的分工
- 公共业务扩展的时候,方便集中管理
缺点:一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低
10.2 加深理解
10.3 动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类使动态生成的,不是直接写好的
- 动态代理分为两大类:基于接口的和基于类的
- 基于接口:JDK动态代理
- 基于类 :chlib
- java字节码实现:javasist
需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序
11.AOP
11.1 什么是AOP
AOP使是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP
的延续,是软件开发的一个热点,也是Spring框架的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
11.2 AOP在Spring中的作用
提供声明式事务,允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法和功能,即使与业务逻辑无关的,仍需要关注的部分,就是横向关注点。如日志、安全、缓存、事务等等。。。
- 切面:横向关注点被模块化的特殊对象,他是一个类
- 通知:切面必须要完成的工作,他是类中的一个方法。
- 目标:被通知对象
- 代理:向目标对象应用通知之后创建的对象
- 切入点:切面通知执行的“地点”的定义
- 连接点:与切入点匹配的执行点
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
AOP在不改变原有代码的情况下,去增加新的功能
11.3 使用Spring实现AOP
使用AOP需要导入一个依赖包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
方式一:使用Spring的API接口【抓哟SpringAPI接口实现】
方式二:自定义来实现AOP【主要是切面定义】
方式三:使用注解实现
12.整合Mybatis
12.1 mybatis
步骤:
1.导入相关jar包
- junit
- mybatis
- mysql数据库
- spring相关
- aop织入
- mybatis-spring【new】
2.编写配置文件
3.测试
12.2 Mybatis-spring
- 编写数据源配置
- sqlSessionFactory
- sqlSessionTemplate
- 需要给接口加实现类
- 将自己写的实现类,注入到Spring中