Spring学习笔记

待更新

前置知识:

Servlet原理

image-20210712172226575

MVC三层架构

model view controller

  1. 早期开发架构

image-20210712184552393

用户访问控制层,控制层就可以直接操作数库;

1
2
3
4
5
servlrt-->CRUD-->database
弊端:臃肿,难以维护

架构:没有什么是加一层解决不了的
eg. JDBC
  1. MVC架构

image-20210712190733391

Model:

  • 业务处理:业务逻辑(Service)
  • 数据持久化:CRUD (Dao)

View:

  • 展示数据
  • 提供链接发起Servlet请求

Controller:(servlet)

  • 接收用户的请求:(req:请求参数,Session信息…)
  • 交给业务层处理对应的代码
  • 控制视图的跳转
1
登录-->接收用户的登录请求-->处理用户的请求(获取登录的参数,username,password)-->交给业务层处理登陆业务(判断用户名密码是否正确:事务)-->DAO层查询用户名密码是否正确-->数据库

反射

导入配置文件

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->  
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>

Spring优良特性

  • 非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API

  • 控制反转:IOC——Inversion of Control,指的是将对象的创建权交给 Spring 去创建。使用 Spring 之前,对象的创建都是由我们自己在代码中new创建。而使用 Spring 之后。对象的创建都是由给了 Spring 框架。

  • 依赖注入:DI——Dependency Injection,是指依赖的对象不需要手动调用 setXX 方法去设置,而是通过配置赋值。

  • 面向切面编程:Aspect Oriented Programming——AOP

  • 容器:Spring 是一个容器,因为它包含并且管理应用对象的生命周期

  • 组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。

  • 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上 Spring 自身也提供了表述层的 SpringMVC 和持久层的 Spring JDBC)

总结: Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的容器(框架)!

IOC

控制反转:通常new一个实例,控制权由程序员控制,而”控制反转”是指new实例工作不由程序员来做而是交给Spring容器来做

配置文件:beans.xml

1
2
3
4
5
6
7
8
9
10
11
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="hello" class="com.geekpig.pojo.hello">
<!--给对象中的属性设置一个值-->
<property name="str" value="Spring"/>
</bean>
</beans>

IOC创建对象的方式

多种,最常用为直接用参数名设置。

1
2
3
<bean id="user" class="com.geekpig.pojo.user">
<property name = "name" value = "gxx"/>
</bean>

总结:在配置文件加载的时候,**容器(ApplicationContext)**中管理的对象就已经被初始化了!

Spring配置

alias

1
2
3
<alias name="user" alias="userNew"/>

User user = (User) context.getBean("userNew");

bean

1
2
3
4
5
6
7
8
<!--
id: bean 的唯一标识符,也就相当于对象名
class: bean 对象所对应的全限定名: 包名 + 类型
name: 也就是起别名 而且name可以取多个别名
-->
<bean id="userT" class="edu.cqupt.pojo.UserT" name="userT2,u2,u3,u4" >
<constructor-arg name="name" value="shilin"/>
</bean>

import

可以将多个配置文件,导入合并为一个

1
2
3
4
//在ApplicationContext.xml里
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>

依赖注入(Dependency Injection)

构造器注入

set方式注入

  • 依赖:bean对象的创建依赖于容器!
  • 注入:bean对象的所有属性,由容器来注入!

普通注入

1
2
3
<bean id="student" class="edu.cqupt.pojo.Student">
<property name="name" value="shi_lin"/>
</bean>

Beans注入

1
2
3
4
5
6
<bean id="address" class="edu.cqupt.pojo.Addresss">
<property name="address" value="重庆"/>
</bean>

<!--Bean注入: ref-->
<property name="addresss" ref="address"/>

数组&list&map&set注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!--数组注入: array-->
<property name="books">
<array>
<value>Java 程序设计</value>
<value>Python 从入门到精通</value>
<value>MYSQL 必知必会</value>
</array>
</property>


<!--List 注入-->
<property name="hobbies">
<list>
<value>编程</value>
<value>听音乐</value>
<value>看电影</value>
</list>
</property>


<!--Map 注入-->
<property name="card">
<map>
<entry key="学生卡" value="1234567"/>
<entry key="身份证" value="123453232367"/>
<entry key="银行卡" value="3332434343434343"/>
</map>
</property>

<!--Set 注入-->
<property name="games">
<set>
<value>LOL</value>
<value>王者荣耀</value>
<value>BOB</value>
</set>
</property>

Null注入

1
2
3
4
<!--Null 注入-->
<property name="wife">
<null/>
</property>

Properties注入

1
2
3
4
5
6
7
8
9
<!--properties 注入-->
<property name="info">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/mydb</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>

C和P命名注入

注意:p命名和c命名不能直接使用,需要导入xml约束。

P命名空间注入

1
2
3
xmlns:p="http://www.springframework.org/schema/p"

<bean id="user" class="edu.cqupt.pojo.User" p:name="shi-lin" p:age="18"/>

C命名空间注入

1
2
3
xmlns:c="http://www.springframework.org/schema/c"

<bean id="user2" class="edu.cqupt.pojo.User" c:name = "shi-lin2" c:age="18"/>

Bean的自动装配

  • 自动装配是Spring满足bean依赖的一种方式!

  • Spring会在上下文中自动寻找,并自动给bean装备属性

  • 在Spring中有三种装配的方式

    • 在xml中显示的装配
    • 在java中显示配置
    • 隐式的自动装配bean

ByName

1
2
3
4
5
6
<!-- byNmae 会自动在容器上下文中查找和自己对象set方法后面的值对应的id -->
<bean id="people" class="edu.cqupt.pojo.People" autowire="byName">
<property name="name" value="shi-lin"/>
<!--<property name="cat" ref="cat"/>-->
<!--<property name="dog" ref="dog"/>-->
</bean>

ByType

1
2
3
4
5
6
7
8

<!-- byName 会自动在容器上下文中查找和自己对象set方法后面的值对应的id -->
<!-- byType 会自动在容器上下文中查找和自己对象属性类型相同的bean -->
<bean id="people" class="edu.cqupt.pojo.People" autowire="byType">
<property name="name" value="shi-lin"/>
<!--<property name="cat" ref="cat"/>-->
<!--<property name="dog" ref="dog"/>-->
</bean>
  • 小结:
    • byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值唯一
    • byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致

注解

  • JDK 1,5 开始支持注解、 Spring 2.5 开始支持注解
  • 要使用注解
    • 导入约束。 contex约束
    • 配置注解的支持<context:ananotation-config/>

配置文件

1
2
3
4
5
6
7
8
9
10
11
<?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>

@Autowired

直接在属性上使用即可,也可以在set方式上使用,使用AutoWired我们可以不用编写Set方法了,前提是这个自动的属性在IOC(Spring)容器中存在,且符合名字byName

1
2
3
4
5
6
7
8
9
10
11
// required = false 说明这个对象可以为null,否则不允许为空
@Autowired(required = false)
private Dog dog;
@Autowired
private Cat cat;
private String name;

//Autowired源码
public @interface Autowired {
boolean required() default true;
}
  • 如果自动装配的环境比较复杂,自动装配无法通过一个注解【@Autuowired】完成的时候,我们可以使用@Qualifier(value = “xxx”)去配合@Autuowired使用,指定一个唯一的bean注入使用。

@Resource

相当于@Autiwired和@Qualifier的组合,功能强大,是Java提供的类库中的

小结:

@Resource 和@Autowired的区别:

  • 都是用来自动装配的,都可以放在属性字段上

  • @Autowired 通过bytype的方式实现,而且必须要求这个对象存在【常用】

  • @Resource 默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错。

使用注解开发

需要导入aop的依赖包,此外还要导入context约束,增加注解的支持。

1
2
3
4
5
6
7
8
9
10
11
12
<?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:component-scan base-package="edu.cqupt"/>
<context:annotation-config/>
</beans>
  • bean

@Component: 组件,放在类上,说明这个类被Spring管理了,就是bean!

等价于: <bean id="user" class="edu.cqupt.pojo.User"/>

  • 属性如何注入

@Value(“shi-lin”)

等价于: < property name ="name" value ="shi-lin" />

  • 衍生的注解

  • @Component有几个衍生的注解,我们在web开发中,会安装mvc三层架构分层。

    • dao【@Repository
    • service【@Service
    • controller【@Controller

    这四个注解功能都是一样的,都是代表将某个类注册到Spring中,转配Bean

  • 自动装配

    • @Autowired: 自动装配通过类型,名字– 如果 若果Autowired不能唯一自动转配上属性,则需要通过@Qualified(value=”xxx”)
    • @Nullable: 字段标记了这个注解,说明这个字段可以为null
    • @Resource: 自动装配通过名字,类型
  • 作用域

    • @Scope(“singleton”)单例模式
    • @Scope(“prototype”)原型模式
  • 小结

    • xml 与 注解:
      • xml:更加万能,适用于任何场合、维护简单方便
      • 注解: 不是自己的类,使用不了,维护相对复杂

最佳实践方式:

  • xml用来管理Bean

  • 注解只用于属性注入

  • 在使用的过程中,只需要注意一个问题,必须让注解生效,开启注解支持

1
2
3
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="comm.geekpig"/>
<context:annotation-config/>

Java Config实现配置

我们现在要完全不使用Spring的.xml配置了,全权交给Java来做!

JavaConfig是Spring的一个子项目,在Spring4之后,它变成了核心功能

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component  // 说明这个类被Spring接管了,注册到了容器中
public class User {

private String name;
public String getName() {
return name;
}
@Value("shi-lin") // 属性注入值
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//这个也会被Spring容器托管,注册到容器中,因为他本来就是一个@Component
// @Configuration代表这就是一个配置类,就和之前的beans.xml一样
@Configuration
@ComponentScan("edu.cqupt.pojo")
@Import(MyConfig2.class)
public class MyConfig {
@Bean
// 注册一个bean,就相当于之前写的一个bean标签
// 这个方法的名字就相当于bean标签中的id属性,方法的返回值就相当bean标签的class
public User user(){
return new User(); //就是返回要注入的bean对象。
}

}
@Configuration
public class MyConfig2 {
}

测试类

1
2
3
4
5
6
7
8
public class MyTest {
public static void main(String[] args) {
// 如果完全使用了配置类方式去做,我们就只能通过AnnotationConfigApplicationContext上下文来获取容器,通过配置类的class对象加载!
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);//加载配置类
User user = context.getBean("user", User.class);
System.out.println(user.getName());
}
}

这种纯Java的配置方式,在SpringBoot中随处可见!

代理模式

Spring AOP 的底层!

  • 静态代理
  • 动态代理

静态代理

代码步骤

  • 接口

  • 真实角色

  • 代理角色

  • 客户端访问代理角色

动态代理

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2022 Doke
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信