一、Spring简介
Spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架
Spring的官网:https://spring.io/
spring的目的是使现有的技术更加容易使用,本身就是个大杂烩,整合了现有的技术框架
优点
1、Spring是一个开源的免费的框架(容器)
2、Springhi一个轻量级的、非入侵式的框架
3、可以控制反转(IOC),面向切面编程(AOP)
4、支持事务的处理,对框架的整合的支持
Springboot:
1、一个快速开发的脚手架
2、基于Springboot可以快速的开发单个微服务
3、约定大于配置
SpringCloud:
SpringCloud是基于Springboot实现的
二、IOC
控制反转是一种思想
背景:
正常我们开发步骤是
1、dao接口
2、dao实现类
3、service接口
4、service实现类
当用户需求发生改变的时候,代码量过大导致修改一次工作量很大
可以使用set接口实现注入
package service;
import dao.UserDao;
import dao.UserDaoImpl;
import java.util.List;
public class UserServiceImpl implements UserService{
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public UserServiceImpl() {
}
public List getUser() {
return userDao.getUser();
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
使用了set后,程序不再具备主动性,变成被动的接受对象,大大降低耦合性
原本是程序提供给用户可以干什么,现在反转了,用户来控制程序来实现什么样的功能,用户来进行选择。例如有mysql和oracle两个数据库,原本使用哪个进行操作是程序决定的,用户只能被动使用,而反转了,用户选择对应数据库的实现类,来实现数据库的功能,有主动权。
DI(依赖注入)是IOC的一种实现方法
对象由Spring创建、管理、装配
三、配置文件
<?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">
<!-- 用spring来创建对象,在spring这些对象称为bean
bean就是对象
id=变量名
class=new的对象
property相当于给属性赋值
-->
<bean id="mysqlimpl" class="dao.UserDaoImplMysql"/>
<bean id="oraclaimpl" class="dao.UserDaoImplOracle"/>
<bean id="userservice" class="service.UserServiceImpl">
<!-- ref 引用spring容器中已经创建好的bean
value 具体的值,基本数据类型
-->
<property name="userDao" ref="mysqlimpl"/>
</bean>
</beans>
package service;
import dao.UserDao;
import dao.UserDaoImpl;
import java.util.List;
public class UserServiceImpl implements UserService{
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public UserServiceImpl() {
}
public List getUser() {
return userDao.getUser();
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
import dao.UserDaoImplOracle;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;
import service.UserServiceImpl;
public class TestDemo {
@Test
public void test1(){
UserService userService=new UserServiceImpl(new UserDaoImplOracle());
System.out.println(userService.getUser());
}
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserServiceImpl service = (UserServiceImpl) context.getBean("userservice");
System.out.println(service.getUser());
}
}
四、IOC创造对象的方式
1、使用无参构造创建对象(默认)
2、假设我们要使用有参构造创建对象
在配置文件被加载的时候,对象就都被创建好了
<?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">
<!-- 用spring来创建对象,在spring这些对象称为bean
bean就是对象
id=变量名
class=new的对象
property相当于给属性赋值
-->
<bean id="hello1" class="pojo.Hello">
<property name="str" value="spring"/>
</bean>
<!-- 第一种 通过下标来设置-->
<bean id="hello2" class="pojo.Hello">
<constructor-arg index="0" value="kerwin"/>
</bean>
<!-- 第二种 如果有两个一样的类型的参数 则不行-->
<bean id="hello3" class="pojo.Hello">
<constructor-arg type="java.lang.String" value="zhangsan"/>
</bean>
<!-- 第三种 直接通过参数名来设置-->
<bean id="hello4" class="pojo.Hello">
<constructor-arg name="str" value="lisi"/>
</bean>
</beans>
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Hello;
public class TestDemo {
@Test
public void test1(){
// 获取spring上下文对象
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
System.out.println("开始");
// 从上下文对象取bean
Hello hello1 = (Hello) context.getBean("hello1");
Hello hello2 = (Hello) context.getBean("hello2");
Hello hello3 = (Hello) context.getBean("hello3");
Hello hello4 = (Hello) context.getBean("hello4");
System.out.println(hello1.toString());
System.out.println(hello2.toString());
System.out.println(hello3.toString());
System.out.println(hello4.toString());
}
}
五、配置文件的标签
1、别名
<!-- 设置别名,可以通过别名获得到对应的bean-->
<alias name="hello1" alias="helloNew"/>
2、Bean的配置
<!-- id:bean的唯一标识 相当于所学的对象名
class:bean对象对应的全限定名 包名+类型
name:也是别名 name可以取多个别名 ,和;分割都可以
-->
<bean id="hello5" class="pojo.Hello" name="hello,helloa;hellob">
<constructor-arg name="str" value="lisi"/>
</bean>
3、import合并配置文件
<!-- import一般用于团队开发,可以将多个配置文件,导入合并为一个-->
<import resource="spring1.xml"/>
<import resource="spring2.xml"/>
<import resource="spring3.xml"/>
六、DI依赖注入
1、构造器注入
2、set注入
依赖:bean对象的创建依赖于容器
注入:bean中的所有属性,由容器注入
<?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="address" class="pojo.Address"/>
<bean id="student" class="pojo.Student">
<!-- 第一种 普通值用value注入-->
<property name="name" value="kerwin"/>
<!-- 第二种 Bean注入-->
<property name="address" ref="address"/>
<!-- 第三种 注入数组-->
<property name="books">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
</array>
</property>
<!-- 注入list-->
<property name="hobbys">
<list>
<value>代码</value>
<value>听歌</value>
</list>
</property>
<!-- 注入map-->
<property name="card">
<map>
<entry key="name" value="kerwin"/>
<entry key="age" value="18"/>
</map>
</property>
<!-- 注入集合-->
<property name="games">
<set>
<value>LOL</value>
<value>CF</value>
<value>COC</value>
</set>
</property>
<!-- 设置为空-->
<property name="wife" value=""/>
<!-- 注入properties-->
<property name="info">
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
</beans>
3、拓展依赖注入
需要先导入xml
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 加入xmlns:p="http://www.springframework.org/schema/p" 使用p空间-->
<!-- p命名注入,直接注入属性的值 相当于property-->
<bean id="user" class="pojo.User"
p:age="18"
p:name="kerwin"/>
<!-- 加入xmlns:c="http://www.springframework.org/schema/c" 使用c空间-->
<!-- c命名注入,通过构造器注入,需要有参构造器,相当于constructor-arg -->
<bean id="user1" class="pojo.User" c:age="18" c:name="kerwin"/>
</beans>
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml");
// 可以在参数里直接指定对象类型
User user = context.getBean("user", User.class);
System.out.println(user.toString());
}
七、bean的作用域
1、单例模式(Spring默认)
<bean id="user1" class="pojo.User" scope="singleton"/>
2、原型模式
每次从容器中get的时候,都会产生一个新的对象
<bean id="user22" class="pojo.User" scope="prototype"/>
3、其他的request、session、application、websocket这些都是在web开发中用的到
八、Bean的自动装配
自动装配是Spring满足bean依赖的一种方式
Spring在上下文自动寻找,自动给bean配置
Spring中的三种装配方式
1、在xml中显式配置
2、在java中配置
3、隐式自动装配bean
<?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="cat" class="pojo.Cat"/>
<bean id="dog" class="pojo.Dog"/>
<!-- autowire 来自动装配 byname 需要id对应属性名
byName:会自动在容器上下文查找和自己set方法后面的值对应的beanid
byType:会自动在容器上下文查找和自己对象类型相同的bean
-->
<bean id="people" class="pojo.People" autowire="byName">
<property name="name" value="kerwin"/>
</bean>
</beans>
小结:
1、byname的时候,需要保证所有的bean的id唯一,并且这个bean需要和注入的属性的set方法的值一致
2、bytype的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性类型一致
九、使用注解实现自动装配
jdk1.5 spring2.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"
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、导入约束
2、配置注解的支持
@Autowired
直接在属性上使用即可 也可以在set方法上使用
使用autowired可以不用写set,前提是自动装配的属性在IOC容器中,并且符合byname名字
@Nullable 字段标记这个注解,代表字段可以为null
// 如果显示标记了required = false 代表对象可以为null 否则不允许为空
@Autowired(required = false)
// 可以指定cat对应的 bean的id
@Qualifier(value = "name123")
private Cat cat;
用@Resource(name=“name1”)也可以,这是java原生注解
@Resource和@Autowired的区别:
1、都是用来自动装配的,都可以放在属性字段上
2、@Autowired通过byType的方式实现,而且必须要求这个对象存在
3、@Resource默认通过byName的方法实现,找不到,则通过byType实现,如果两个都找不到则报错