Spring学习笔记
1.1 简介
Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
组成:
Springboot:快速开发的脚手架
基于Spring boot可以快速开发一个微服务
约定大于配置
Springcloud:基于Spring boot实现的
maven导依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
</dependencies>
1.2 IOC(控制反转)
1.2.1 第一个Spring程序
实体类:
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 + '\'' +
'}';
}
beans.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-3.0.xsd">
<bean id="hello" class="com.candy.pojo.Hello">
<property name="name" value="Hello World!"/>
</bean>
</beans>
id:变量名 class=new 的对象 property:相当于实体类中的属性
测试类:
public static void main(String[] args) {
//获取Spring的上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//获取hello对象
Hello hello =(Hello) context.getBean("hello");
System.out.println(hello);
}
hello对象由Spring创建的,对象属性由Spring容器设置的
1.2.2 Spring配置
1.2.2.1 alias(别名)
<alias name="hello" alias="hi"></alias>
Hello hello =(Hello) context.getBean("hi");
1.2.2.2 bean
Id: bean的唯一标识符,对应对象名
class:bean对象所对应的全限定名:包名+类型
Name : 别名 功能类似于,而且可以创建多个别名
<bean id="hello" class="com.candy.pojo.Hello" name="hii,hellohi">
<property name="name" value="Hello World!"/>
</bean>
Hello hello =(Hello) context.getBean("hellohi");
1.2.2.3 import(applicationContent.xml)
一般用于团队开发,可以将多个配置文件导入合并成一个
<import resource="beans.xml"/>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContent.xml");
1.3 DI依赖注入
bean对象的创建依赖于容器,bean对象中的所有属性由容器注入
1.3.1 Set方式注入
-
直接用value注入
<property name="name" value="马嘉祺"/>
ApplicationContext content = new ClassPathXmlApplicationContext("beans.xml"); Student stu = (Student) content.getBean("student"); System.out.println(stu.getName());
-
bean注入—— ref
<bean id="address" class="com.candy.pojo.Address"> </bean> <bean id="student" class="com.candy.pojo.Student" > <property name="address" ref="address"/> </bean>
-
数组注入——
<bean id="student" class="com.candy.pojo.Student" > <property name="books"> <array> <value>五年高考三年模拟</value> <value>黄冈模拟真题卷</value> <value>衡水期末试卷</value> </array> </property> </bean>
-
List注入——
<bean id="student" class="com.candy.pojo.Student" > <property name="hobbys"> <list> <value>听歌</value> <value>游泳</value> </list> </property> </bean>
-
Map注入——
<bean id="student" class="com.candy.pojo.Student" > <property name="card"> <map> <entry key="电话" value="15869189055"/> <entry key="身份证号" value="37012319981125xxxx"/> </map> </property> </bean>
-
Set注入——
<bean id="student" class="com.candy.pojo.Student" > <property name="games"> <set> <value>英雄联盟</value> <value>开心消消乐</value> </set> </property> </bean>
-
空注入
空值注入:
<bean id="student" class="com.candy.pojo.Student" > <property name="wife" value=""></property> </bean>
设置为null:
<bean id="student" class="com.candy.pojo.Student" > <property name="wife" > <null></null> </property> </bean>
-
Properties注入——
<bean id="student" class="com.candy.pojo.Student" > <property name="info"> <props> <prop key="学号">202120502028</prop> <prop key="性别">female</prop> </props> </property> </bean>
1.3.2 拓展注入
1.3.2.1 p命名空间注入(属性注入)
p:property
//先在beans中引入
xmlns:p="http://www.springframework.org/schema/p"
<bean id="user" class="com.candy.pojo.User" p:name="丁程鑫" p:age="20">
</bean>
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("userBean.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
}
1.3.2.2 c命名空间注入(构造器注入)
c:construct
//先在beans中引入
xmlns:c="http://www.springframework.org/schema/c"
<bean id="user2" class="com.candy.pojo.User" c:name="宋亚轩" c:age="18"/>
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("userBean.xml");
User user = context.getBean("user2", User.class);
System.out.println(user);
}
注意:
p命名需要实体类中有无参构造方法,c命名需要实体类需要有参构造方法
1.4 Bean的自动装配
自动配置是Spring满足bean依赖的一种方式
Spring会在上下文中自动寻找,并给bean装配属性
在Spring中有三种配置方式:
1.在xml中
2.在java中
3.隐式的自动装配【重点】
1.4.1 ByName自动装配
会自动在容器上下文查找和实体类中Set方法对应的bean-id
<bean id="cat" class="com.candy.pojo.Cat"/>
<bean id="dog" class="com.candy.pojo.Dog"/>
<bean id="person" class="com.candy.pojo.Person" autowire="byName">
<property name="name" value="宋亚轩" />
</bean>
1.4.2 ByType自动装配
会自动在容器上下文查找和实体类类型对应的bean
<bean id="cat" class="com.candy.pojo.Cat"/>
<bean id="dog" class="com.candy.pojo.Dog"/>
<bean id="person" class="com.candy.pojo.Person" autowire="byType">
<property name="name" value="宋亚轩"/>
</bean>
1.4.3 使用注解自动装配
使用注解需要导入一些支持:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
1.4.3.1 @Autowired【常用】
直接在属性上使用
public class Person {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
}
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="cat" class="com.candy.pojo.Cat"/>
<bean id="dog" class="com.candy.pojo.Dog"/>
<bean id="person" class="com.candy.pojo.Person" />
</beans>
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Person person = context.getBean("person",Person.class);
person.getCat().shout();
person.getDog().shout();
}
}
1.4.3.2 @Resource
java原生注解
@Resource
private Cat cat;
@Resource
private Dog dog;
private String name;
@Autowire和@Resource的区别:
@Autowire默认按照ByType查找,如果存在多个对象在按照ByName查找
@Resource默认按照ByName查找,如果找不到再按照ByType查找
1.5 使用注解开发
1.5.1 准备工作
//指定要扫描注解的包
<context:component-scan base-package="com.candy.pojo"/>
@Component
放在实体类上面,作用类似于
@Component
public class User {
public String name="刘耀文";
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user.name);
}
@Value
放在属性上面,作用类似于
@Component
public class User {
@Value("张真源")
public String name;
}
1.5.2 衍生注解
以下衍生注解等价于@Component,将某个类注册到Spring容器中,装配bean
- Dao: @Repository
- Service: @Service
- Controller: @Controller
1.5.3 使用Java方式配置Spring
Javaconfig
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("严浩翔")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}}
@Configuration//配置类 作用类似于beans.xml
public class CandyConfig {
@Bean//bean的id就是方法名,方法的返回值就是class属性
public User getUser(){
return new User();
}
}
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(CandyConfig.class);
User getUser = (User) context.getBean("getUser");
System.out.println(getUser.getName());
}
}
1.6 代理模式
Spring AOP的底层
- 静态代理
- 动态代理
1.6.1 静态代理
角色分析:
- 抽象角色:一般会使用接口或者抽象类
- 真实角色:被代理的角色
- 代理角色:代理真实角色,一般会进行一些操作
- 客户:访问代理对象的人
1.6.2 动态代理
角色和静态代理一样
动态代理的代理类是动态的
动态代理分为两大类:基于接口的动态代理、基于类的动态代理
- 基于接口——JDK动态代理
- 基于类——cglib
- 认识两个类:Proxy代理、InvocationHandler调用处理程序
1.7 AOP(面向切面编程)
什么是AOP?
要理解切面编程,就需要先理解什么是切面。用刀把一个西瓜分成两瓣,切开的切口就是切面;炒菜,锅与炉子共同来完成炒菜,锅与炉子就是切面。web层级设计中,web层->网关层->服务层->数据层,每一层之间也是一个切面。编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。
1.7.1 引入AOP的包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
1.7.2 使用注解实现
@Before: 标识一个前置增强方法,相当于BeforeAdvice的功能.
@After: final增强,不管是抛出异常或者正常退出都会执行.
@AfterReturning: 后置增强,似于AfterReturningAdvice, 方法正常退出时执行.
@AfterThrowing: 异常抛出增强,相当于ThrowsAdvice.
@Around: 环绕增强,相当于MethodInterceptor.
execution:用于匹配方法执行的连接点;