spring学习-狂神说-day01
一、什么是spring
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.8.RELEASE</version> </dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.8.RELEASE</version> </dependency>
优点:
- Spring是一个开源的免费的框架(容器)
- Spring是一个轻量级的,非入侵式的框架
- 控制反转(IOC)和面向切面编程(AOP)
- 支持事务的处理
- 对框架整合的支持
总结一句话:Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
Spring的组成:

Spring学习计划

Spring Boot
- 一个快速开发的脚手架
- 基于Springboot可以快速开发单个微服务
- 约定大于配置
SpringCloud
- SpringCloud是基于SpringBoot实现的
因为现在大多数公司的使用SpringBoot进行快速 开发,学习SpringBoot的前提,需要完成掌握Spring及SpringMVC,承上启下作用,SpringBoot又是学习SpringCloud的基础。
缺点:需要有很多配置
二、IOC理论指导
原来方式:
1、UserDao接口
2、UserDaoImpl
3、UserService业务接口
4、UserServiceImpl业务实现类
在我们的之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码,如果程序代码量十分大,修改一次的成本就十分昂贵
我们使用了一个Set接口实现,已发生了革命必的变化:
private IUserDao userDao; public void SetUserDao(IUserDao userDao){ this.userDao = userDao; }
之前程序是主动创建对象,控制权在程序员手上,
使用了set注入后,程序不再具有主动性,而是变成了被动接受对象,由使用者在外面指定创建什么类型的对象。
这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注 在业务的实现上。


Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
采用XML方式配置Bean的时候,Bean的定义信息和实现分离的,而采用注解的方式可以把两合为一体;Bean的定义信息直接以注解的形式定义在实现类中,从则达到了零配置的目的。
控制反转是一种通用描述(XML配置或注解),并通过第三方去生产或获取特定对象的方式,在Spring中实现控制返回的是IOC容器,其实现方法是依赖注入(Dependency Injection DI).
以下为HelloDemo的程序:
Hello类定义:
package com.fengfang.dao; /** * @Description TODO * @Author liuxh * @Date 2020/8/11 15:23 **/ public class Hello { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("hello " +name); } }
配置文件内容:
<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"> <!-- 使用Spring来创建对象,在SPring中,这些都称为bean bean等于对象,new hello() Hello hello = new Hello(); 类型 变量名 = new 类型(); id 变量名 class new 的对象 property:相当于对象中的属性设置 --> <bean id="hello" class="com.fengfang.dao.Hello" > <property name="name" value="testaa"></property> </bean> </beans>
测试代码:
package com.fengfang.test; import com.fengfang.dao.Hello; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Description TODO * @Author liuxh * @Date 2020/8/11 15:25 **/ public class HelloTest { public static void main(String[] args) { // 获取Spring的上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); // 我们的对象现在都在spring管理 Hello hello = (Hello) context.getBean("hello"); hello.show(); } }
测试结果如下:

IOC创建对象的方式:
- 使用无参构造函数创建对象
- 假设我们要使用有参构造函数创建对象
- 下标赋值
<!-- 使用有参构造函数:下标赋值--> <bean id="userNew" class="com.fengfang.domain.User"> <constructor-arg index="0" value="这是一个测试名称"></constructor-arg> </bean>
- 使用参数的类型匹配
<!-- 使用有参构造函数:类型赋值,有多个参数会有问题不建议使用--> <bean id="userType" class="com.fengfang.domain.User"> <constructor-arg type="java.lang.String" value="这是一个测试名称"></constructor-arg> </bean>
- 使用参数名称来创建:
<!-- 使用有参构造函数:参数名称赋值--> <bean id="user" class="com.fengfang.domain.User"> <constructor-arg name="name" value="这是一个测试名称"></constructor-arg> </bean>
Spring的bean中,若有定义了,就算没有被调用实例化,也会发现这个实例已经在容器中创建了。
如测试代码:
package com.fengfang.domain; /** * @Description TODO * @Author liuxh * @Date 2020/8/11 17:28 **/ public class Student { private String name; public Student(){ System.out.println("这是Student无参构造函数!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + '}'; } }
package com.fengfang.domain; /** * @Description TODO * @Author liuxh * @Date 2020/8/11 17:05 **/ public class User { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } // public User() { // System.out.println("user的无参构造函数!"); // // } // public User(String name){ this.name = name; } }
<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="user" class="com.fengfang.domain.User"> <property name="name" value="liuxh"></property> </bean>--> <!-- 使用有参构造函数:下标赋值--> <!-- <bean id="user" class="com.fengfang.domain.User"> <constructor-arg index="0" value="这是一个测试名称"></constructor-arg> </bean>--> <!-- 使用有参构造函数:类型赋值,有多个参数会有问题不建议使用--> <!-- <bean id="user" class="com.fengfang.domain.User"> <constructor-arg type="java.lang.String" value="这是一个测试名称"></constructor-arg> </bean>--> <!-- 使用有参构造函数:参数名称赋值--> <bean id="user" class="com.fengfang.domain.User"> <constructor-arg name="name" value="这是一个测试名称"></constructor-arg> </bean> <bean id="student" class="com.fengfang.domain.Student"></bean> </beans>
上面是类代码及beans的配置文件
测试代码:
package com.fengfang.test; import com.fengfang.domain.User; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Description TODO * @Author liuxh * @Date 2020/8/11 17:07 **/ public class UserTest { public static void main(String[] args) { // User user = new User(); // Spring容器,就类似于婚介网站 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); // 这里并没有获取Student类,但是发会现Student的无参构造函数也被初始化了 User myUser = (User) context.getBean("user"); System.out.println(myUser.toString()); } }
执行测试结果发现,两个实例的构造函数都有执行,如下图:

三:Spring配置
- 别名
<!-- 设置user的别名为userAlias--> <alias name="user" alias="userAlias"/>
在测试代码里面使用别名也可以调用:
package com.fengfang.test; import com.fengfang.domain.User; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Description TODO * @Author liuxh * @Date 2020/8/11 17:07 **/ public class UserTest { public static void main(String[] args) { // User user = new User(); // Spring容器,就类似于婚介网站 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); // 这里并没有获取Student类,但是发会现Student的无参构造函数也被初始化了 User myUser = (User) context.getBean("userAlias"); System.out.println(myUser.toString()); } }
- Bean配置
<!-- id 为bean的唯一标识符,也就是相当于我们学的对象名 class :bean对象对应的全限定类名:包名+类名 name :也是别名,可以取多个别名如:name='n1,n2' property: name: value: --> <bean id="user" class="com.fengfang.domain.User"> <property name="name" value="liuxh"></property> </bean>
- Import
这个import,一般用于团队开发使用,他可以将多个配置文件,导入合并为一个
假设,项目项目中有三个人开发,分别是张三,李四和王五,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以使用import将所有人的bean.xml合并为一个总的,如总的配置文件为applicationContext.xml,则定义以下:
<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"> <import resource="beans2.xml"/> <import resource="beans.xml"/> <import resource="beans3.xml" /> </beans>
使用时,就直接使用applicationContext.xml载入就行,会将所有bean在容器中初始化。
四:依赖注入(DI)
1、构造器注入,前面已经说过
2、Set方式注入【重点】
依赖注入:set注入
- 依赖:bean对象的创建依赖容器
- 注入:bean对象的所有属性,由容器来注入
环境搭建:
1、复杂类型
package com.fengfang.domain; /** * TODO * * @author liuxh * @date 2020/8/11 21:38 **/ public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
2、真实测试对象
package com.fengfang.domain; import java.util.*; /** * TODO * * @author liuxh * @date 2020/8/11 21:38 **/ public class Student { @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", address=" + address + ", books=" + Arrays.toString(books) + ", hobys=" + hobys + ", age=" + age + ", card=" + card + ", games=" + games + ", info=" + info + ", wife='" + wife + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String[] getBooks() { return books; } public void setBooks(String[] books) { this.books = books; } public List<String> getHobys() { return hobys; } public void setHobys(List<String> hobys) { this.hobys = hobys; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Map<String, String> getCard() { return card; } public void setCard(Map<String, String> card) { this.card = card; } public Set<String> getGames() { return games; } public void setGames(Set<String> games) { this.games = games; } public Properties getInfo() { return info; } public void setInfo(Properties info) { this.info = info; } public String getWife() { return wife; } public void setWife(String wife) { this.wife = wife; } private String name; private Address address; private String[] books; private List<String> hobys; private Integer age; private Map<String,String> card; private Set<String> games; private Properties info; private String wife; }
3、beans.xml
<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="student" class="com.fengfang.domain.Student"> <property name="name" value="aaron"></property> </bean> </beans>
4、测试类
package com.fengfang.test; import com.fengfang.domain.Student; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * TODO * * @author liuxh * @date 2020/8/12 10:03 **/ public class DITest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); } }
对于属性注入有很多类型可以注入,如下面配置文件示例:
<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="student" class="com.fengfang.domain.Student"> <!-- 普通类型注入--> <property name="name" value="aaron"></property> <!-- bean 注入,直接用ref--> <property name="address" ref="address"/> <!-- 数组注入--> <property name="books"> <array> <value>红楼梦</value> <value>我的自白</value> <value>活着</value> <value>西游记</value> </array> </property> <!-- list注入--> <property name="hobys"> <list> <value>电影</value> <value>唱歌</value> <value>跳舞</value> </list> </property> <!-- map注入--> <property name="card"> <map> <entry key="身份证" value="123456789"></entry> <entry key="银行卡" value="987654321"></entry> </map> </property> <!-- set 注入--> <property name="games"> <set> <value>LOL</value> <value>王者</value> <value>红警</value> </set> </property> <!-- properties注入--> <property name="info"> <props> <prop key="driver">val1</prop> <prop key="url">val2</prop> <prop key="username">val3</prop> <prop key="password">val3</prop> </props> </property> <property name="age" value="25"></property> <!-- 对于null的注入--> <property name="wife"> <null/> </property> </bean> <!-- 定义一个新的bean--> <bean id="address" class="com.fengfang.domain.Address"> <property name="address" value="广东省东莞市"></property> </bean> </beans>
3、拓展方式注入
使用C命名空间或P命名空间
1、若使用P命名空间,其实是基于Set注入方式
在配置文件引入约束,下面品红色部分内容
<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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
定义方式:p:属性名称
<bean id="user" class="com.fengfang.domain.User" p:name="aaron" p:age="20" p:address="广东东莞"> </bean>
测试代码:
@Test public void testPnamespace(){ ApplicationContext context = new ClassPathXmlApplicationContext("user.xml"); User user = context.getBean("user", User.class); System.out.println(user); }
测试发现是可以对属性进行注入成功的:

2、若使用C命名空间方式,则是基于构造注入方式
增加约束内容,下面品红色内容
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
在类中需增加有参和无参构造函数
package com.fengfang.domain; /** * @Description TODO * @Author liuxh * @Date 2020/8/12 10:49 **/ public class Teacher { private String name; private Integer age; private String courseName; public Teacher() { } public Teacher(String name, Integer age, String courseName) { this.name = name; this.age = age; this.courseName = courseName; } @Override public String toString() { return "Teacher{" + "name='" + name + '\'' + ", age=" + age + ", courseName='" + courseName + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getCourseName() { return courseName; } public void setCourseName(String courseName) { this.courseName = courseName; } }
定义也和P类型
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 原来方式--> <!-- <bean id="teacher" class="com.fengfang.domain.Teacher"> <constructor-arg name="name" value="刘东东"></constructor-arg> <constructor-arg name="age" value="26"></constructor-arg> <constructor-arg name="courseName" value="英语"></constructor-arg> </bean>--> <bean id="teacher" class="com.fengfang.domain.Teacher" c:name="刘东东" c:age="25" c:courseName="英语"></bean> </beans>
测试代码和结果展示:

五、作用域
| Scope | Description |
|---|---|
|
(Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
|
|
Scopes a single bean definition to any number of object instances. |
|
|
Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring |
|
|
Scopes a single bean definition to the lifecycle of an HTTP |
|
|
Scopes a single bean definition to the lifecycle of a |
|
|
Scopes a single bean definition to the lifecycle of a |
1、单例模式
默认使用单例模式,我们发现两个创建的实例是一致的,即如下结果比对:
<bean id="user" class="com.fengfang.domain.User" p:name="aaron" p:age="20" p:address="广东东莞" scope="singleton"> </bean>

2、原型模式
<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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.fengfang.domain.User" p:name="aaron" p:age="20" p:address="广东东莞" scope="prototype"> </bean> </beans>
测试比对结果发现是不一致的

3、其它模式,request、session、application这些只能在Web开发中使用到

浙公网安备 33010602011771号