1.Spring
1.1 简介
-
2002年首次推出Spring的雏形,interface21框架
-
2004正式发布1.0版本
-
解决企业应用开发的复杂性,其理念是使现有的技术更加容易使用!
-
SSH:Struct2+Spring+Hibernate
-
SSM:SpringMvc+Spring+Mybatis
-
下载地址: http://repo.spring.io/release/org/springframework/spring
-
github地址:spring-projects/spring-framework: Spring Framework (github.com)
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
1.2 优点
-
Spring是开源的免费的容器!
-
是一个轻量级的非入侵式的框架!
-
控制反转(IOC),面向切面编程(AOP)
-
支持事务的处理,对框架整合的支持!
1.3 组成
1.4 扩展
-
Spring Boot
- 一个快速开发的脚手架
- 基于SpringBoot快速开发微服务
- 约定大于配置
-
Spring Cloud
- Spring Cloud是基于SpringBoot实现
-
学习SpringBoot的前提是学习Spring和SpringMVC
2、IOC理论推导
原来的写法:
1.UserDao接口
2.UserDaoImpl实现类
3.UserService业务接口
4.UserServiceImpl实现类
在之前的业务中,用户的需求会影响代码,根据用户需求修改原代码成本非常高!
我们使用一个Set接口实现,使用set注入后,程序不再具有主动性
Dao层的实现类:
public class UserDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("获取用户数据");
}
}
public class UserSqlServerImpl implements UserDao{
@Override
public void getUser() {
System.out.println("sqlserver 获取用户数据");
}
}
Service层,不需要写死dao层的代码:
private UserDao userDao;
//利用set进行动态实现值的注入!
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
测试:
public class MyTest {
public static void main(String[] args) {
//用户调用是业务层,dao层不需要接触
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserSqlServerImpl());
userService.getUser();
}
}
控制反转(主动权变了,程序不再具有主动性,变成被动接受对象)这种思想,从本质上解决了问题,程序员不用再去管理对象的创建了。系统的耦合性大大降低
IOC本质:
控制反转IOC(Inversion of Control)是一种设计思想,DI(依赖注入)是实现ioc的一种方法,所谓的控制反转就是:获得依赖对象的方式反转了
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式,在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(DI)
3、HelloSpring
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
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">
<!--使用spring来创建对象,在spring都称为bean
类型 变量名 = new Hello()
id = 变量名
class = new 的对象
property相当于给对象中的属性设置一个值
ref:引用spring容器中创建好的对象
value:具体的值
-->
<bean id="hello" class="com.liu.pojo.Hello">
<property name="str" value="Spring"/>
</bean>
</beans>
测试:
import com.liu.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());
}
}
思考问题:
-
Hello对象是谁创建的?
hello对象是Spring创建的
-
Hello对象的属性是怎么设置的?
hello对象的属性由Spring容器设置的
-
创建bean的时候就创建了对象
这个过程就叫控制反转(原来需要我们new一个对象,现在由容器生成,我们只用从容器中拿即可)
-
控制:谁来控制对象的创建,传统应用程序的对象由程序本身控制创建的,使用spring后,对象由spring来创建
-
反转:程序本身不创建对象,变成被动的接收对象
-
依赖注入:利用set方法进行注入
-
IOC是一种变成思想,由主动的变成变成被动的接收,由spring创建,管理
4、IOC创建对象的方式
1.使用无参构造方法创建对象!默认实现
package com.liu.pojo;
public class User {
private String name;
public User(){
System.out.println("User的无参构造!");
}
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.liu.pojo.User">
<property name="name" value="liuxiang"/>
</bean>
</beans>
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
}
2.通过有参构造实现
- 下标赋值
<!--下标赋值-->
<bean id="user" class="com.liu.pojo.User">
<constructor-arg index="0" value="liuxiang"/>
</bean>
- 类型赋值(不建议使用)
<bean id="user" class="com.liu.pojo.User">
<constructor-arg type="java.lang.String" value="liuxiang"/>
</bean>
- 通过参数名
<bean id="user" class="com.liu.pojo.User">
<constructor-arg name="name" value="刘想"/>
</bean>
5、Spring配置
5.1 别名
<alias name="user" alias="llx"/>
5.2 Bean的配置
id:bean的唯一标识符,相当于对象名
class:bean对象所对应的全限定名(包名+类型)
name:别名,更高级,可以取多个别名(空格,逗号,分号都可以分隔)
5.3 import
一般用于团队开发,可以将多个配置文件导入合并为一个
applicationContext.xml总的配置文件:
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
6、依赖注入
6.1 构造器注入
无参有参构造器注入:
<bean id="user" class="com.liu.pojo.User">
<property name="name" value="liuxiang"/>
</bean>
<bean id="user" class="com.liu.pojo.User">
<constructor-arg name="name" value="刘想"/>
</bean>
<bean id="user" class="com.liu.pojo.User">
<constructor-arg type="java.lang.String" value="liuxiang"/>
</bean>
6.2 set注入(重点)
依赖注入:set注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性由容器来注入
环境搭建:
- 复杂类型
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 + '\'' +
'}';
}
}
- 真实测试
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private Properties info;
- 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.xsd">
<bean id="address" class="com.liu.pojo.Address">
<property name="address" value="深圳"/>
</bean>
<bean id="student" class="com.liu.pojo.Student">
<!--第一种,普通的value值-->
<property name="name" value="刘想"/>
<!--第二种,bean注入-->
<property name="address" ref="address"/>
<!--数组注入-->
<property name="books">
<array>
<value>Java核心</value>
<value>Go语言</value>
<value>黑客技术</value>
<value>JVM</value>
</array>
</property>
<!--List-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>游戏</value>
<value>音乐</value>
</list>
</property>
<!--map-->
<property name="card">
<map>
<entry key="身份证" value="421023111111112222"/>
<entry key="手机号" value="17777776666"/>
</map>
</property>
<!--set-->
<property name="games">
<set>
<value>lol</value>
<value>吃鸡</value>
<value>王者</value>
</set>
</property>
<!--Properties-->
<property name="info">
<props>
<prop key="driver">com.mysql.driver</prop>
<prop key="url">jdbc//mysql:3306</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
</beans>
- 测试类
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);
}
}
- 结果
Student{name='刘想',
address=Address{address='深圳'},
books=[Java核心, Go语言, 黑客技术, JVM],
hobbys=[听歌, 游戏, 音乐],
card={身份证=421023111111112222, 手机号=17777776666},
games=[lol, 吃鸡, 王者],
info={password=123456,
url=jdbc//mysql:3306,
driver=com.mysql.driver,
username=root}}
6.3 扩展方式注入
- P命名注入(就是property)
导入头文件约束:
<beans
xmlns:p="http://www.springframework.org/schema/p"
</beans>
可以注入属性的值!
- c命名空间
就是构造器注入!
导入头文件约束:
<beans
xmlns:p="http://www.springframework.org/schema/c"
</beans>
7、Bean作用域
单例模式(Spring默认机制):全局共享唯一,创建的对象都是一样的
<bean id="user2" class="com.liu.pojo.User" c:age="18" c:name="刘想" scope="singleton"/>
原型模式:创建的对象不一样,每次从容器get的时候都会产生新对象!
<bean id="user2" class="com.liu.pojo.User" c:age="18" c:name="刘想" scope="prototype"/>
其余的request、session、application这些只能在web开发中使用!