一、spring基本介绍
前言:系统的复习一遍spring
概念
- Spring 是轻量级的开源的JavaEE框架
- Spring可以解决企业应用开发的复杂性
- Spring的两大核心部分:IOC和Aop
- IOC:控制反转,将创建对像的过程交给Spring进行管理
- Aop:面对切面,在不修改源代码进行功能增强
特点
-
方便解耦,简化开发
通过IOC容器,对象依赖交予Spring进行控制,避免硬编码带来的程序耦合。并且,不必为单例模式、属性文件解析等底层需求编写代码,专注于上层的应用。
-
Aop编程支持
-
声明式的事务支持
-
方便程序程序
-
方便集成各种优秀框架
-
减低Java EE Api的使用难度
二、入门案例
-
下载最新稳定版
https://repo.spring.io/release/org/springframework/spring
-
打开idea,创建普通工程
-
导入需要的spring的jar包
-
使用spring新建对象。创建普通类,在类中创建普通方法
package com.lfh.spring; public class User { public void add(){ System.out.println("add ...."); } }
-
创建Spring配置文件,在配置文件创建的对象
-
Spring的配置文件是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"> <!--配置User类的创建--> <bean id="user" class="com.lfh.spring.User"></bean> </beans>
-
-
进行测试
package com.lfh.spring.test; import com.lfh.spring.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpring { @Test public void testUserAdd(){ //1.加载spring配置文件 ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml"); //2.获取配置文件创建对象 User user = context.getBean("user",User.class); System.out.println(user); user.add(); } }
三、Spring的IOC
- IOC的底层原理
- IOC接口(BeanFactory)
- IOC操作Bean管理(基于xml)
- IOC操作Bean管理(基于注解)
- IOC概念
控制反转,是面向对象编程的一种设计原则,可以降低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(入门案例便是IOC实现)
-
IOC的底层原理
- xml的解析、工厂模式、反射
-
IOC接口
-
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
-
Spring提供IOC容器实现的两种方式:(两个接口)
- BeanFactory:作用:加载配置文件,IOC容器基本实现,是Spring内部的使用接口,不提供开发人员使用。注意加载配置文件时,不会创建对象,在获取、使用时才创建对象
- ApplicationContext:作用:加载配置文件 BeanFactory的子接口,功能更强大,提供开发人员使用在加载配置文件时,创建配置文件的对象
-
Application接口的实现类
-
ClassPathXmlApplicationContext//src的相对路径
FileSystemXmlApplicationContext//电脑盘的路径
-
-
-
IOC操作Bean管理
- Bean管理的概念
- Spring创建对象:new对象
- Spring注入属性:setting userName
- Bean实现
- 基于xml配置文件方式实现
- 基于注解方式实现
- Bean管理的概念
-
IOC操作Bean管理实现(基于xml方式)
-
Bean管理的创建对象:默认执行无参数构造方法
<!--配置User类的创建--> <bean id="user" class="com.lfh.spring.User"></bean>
- id属性:唯一标识
- class属性:类的全路径
- name属性:和id属性类似,可以使用/等字符
-
Bean管理的注入属性
-
DI:依赖注入,就是注入属性
-
第一种注入使用set方法
package com.lfh.spring; /** * set注入属性 */ public class Book { private String name; public void setName(String name) { this.name = name; } public static void main(String[] args) { Book book = new Book(); book.setName("三体"); } }
<?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"> <!--1.配置User类的创建--> <bean id="user" class="com.lfh.spring.User" ></bean> <!--2.1创建book对象--> <bean id="book" class="com.lfh.spring.Book"> <!--2.2set注入属性--> <property name="name" value="java基础"></property> </bean> </beans>
@Test public void testBookDI(){ //1.加载spring配置文件, BeanFactory context=new ClassPathXmlApplicationContext("bean1.xml"); //2.获取配置文件创建对象, Book book = context.getBean("book", Book.class); System.out.println(book); book.testDemo(); }
-
第二种注入使用有参构造函数
package com.lfh.spring; /* 有参构造注入 */ public class Order { private String orderName; private String address; public Order(String orderName, String address) { this.orderName = orderName; this.address = address; } }
<!--3.1创建order对象--> <bean id="order" class="com.lfh.spring.Order"> <constructor-arg name="orderName" value="茶叶"></constructor-arg> <constructor-arg name="address" value="湛江"></constructor-arg> </bean>
@Test public void testOrderDI(){ //1.加载spring配置文件, BeanFactory context=new ClassPathXmlApplicationContext("bean1.xml"); //2.获取配置文件创建对象, Order order = context.getBean("order", Order.class); System.out.println(order); order.OrderTest(); }
-
-
xml注入其他属性
-
字面量(设置固定值)
-
设置NULL
<bean id="book" class="com.lfh.spring.Book"> <!--2.2set注入属性--> <property name="author"> <null></null> </property> </bean>
-
设置包含特殊符号
<bean id="book" class="com.lfh.spring.Book"> <!--2.2set注入属性--> <property name="name" value="<<java基础>>"> </property> </bean>
<bean id="book" class="com.lfh.spring.Book"> <!--2.2set注入属性--> <property name="name" > <value> <![CDATA[<<三体>>]]> </value> </property> </bean>
-
-
注入属性–外部Bean
-
创建service和dao类
-
在service里调用dao
-
在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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.lfh.spring.service.UserService" id="userService"> <!--注入userDao对象--> <!--ref属性:创建userDAO对象bean便签id值--> <property name="userDao" ref="userDaoImpl"></property> </bean> <bean class="com.lfh.spring.dao.UserDaoImpl" id="userDaoImpl"> </bean> </beans>
-
-
注入属性–内部Bean和级联赋值
-
一对多关系:部门员工
-
在实体类之间表示一对多关系
//部门 package com.lfh.spring.bean; public class Dept { private String dName; public void setdName(String dName) { this.dName = dName; } }
package com.lfh.spring.bean; //员工 public class Emp { private String eName; private String gender; // 员工的部门 private Dept dept; public void seteName(String eName) { this.eName = eName; } public void setGender(String gender) { this.gender = gender; } public void setDept(Dept dept) { this.dept = dept; } }
-
在spring的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--> <bean class="com.lfh.spring.bean.Emp" id="emp"> <property name="dept"> <bean class="com.lfh.spring.bean.Dept" id="dept"> <property name="dName" value="研发部"></property> </bean> </property> <property name="eName" value="小明"></property> <property name="gender" value="man"></property> </bean> </beans>
-
级联赋值
<?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--> <bean class="com.lfh.spring.bean.Emp" id="emp"> <property name="eName" value="小明"></property> <property name="gender" value="man"></property> <!--级联赋值--> <property name="dept" ref="dept"></property> </bean> <bean class="com.lfh.spring.bean.Dept" id="dept"> <property name="dName" value="财务部"></property> </bean> </beans>
<?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--> <bean class="com.lfh.spring.bean.Emp" id="emp"> <property name="eName" value="小明"></property> <property name="gender" value="man"></property> <!--级联赋值--> <property name="dept" ref="dept"></property> <property name="dept.dName" value="xx部"></property> </bean> <bean class="com.lfh.spring.bean.Dept" id="dept"> <property name="dName" value="财务部"></property> </bean> </beans>
-
-
Ioc操作Bean管理(xml注入集合属性)
- 注入数组类型属性
- 注入List集合类型属性
- 注入Map集合类型属性
package com.lfh.spring.collectiontype; import java.util.List; import java.util.Map; public class Stu { private String[] courses; private List<String> list; private Map<String,String> map; public void setCourses(String[] courses) { this.courses = courses; } public void setList(List<String> list) { this.list = list; } public void setMap(Map<String, String> map) { this.map = map; } }
<?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 class="com.lfh.spring.collectiontype.Stu" id="stu"> <!--数组类型--> <property name="courses" > <array> <value>语文</value> <value>数学</value> <value>英语</value> </array> </property> <!--List类型--> <property name="list"> <list> <value>张三</value> <value>法外狂徒</value> </list> </property> <!--map类型--> <property name="map"> <map> <entry key="001" value="搜索"></entry> <entry key="002" value="发现"></entry> </map> </property> </bean> </beans>
优化
<?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 class="com.lfh.spring.collectiontype.Stu" id="stu"> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property> </bean> <bean class="com.lfh.spring.collectiontype.Course" id="course1"> <property name="cname" value="Spring框架"></property> </bean> <bean class="com.lfh.spring.collectiontype.Course" id="course2"> <property name="cname" value="Mybatis框架"></property> </bean> </beans>
优化2
-
-
-
IOC操作Bean管理(FatoryBean)
-
Spring有两种bean,一种普通bean,一种工厂bean(FactoryBean)
-
普通bean:返回类型和定义类型一致
-
工厂bena:返回类型和定义类型可以不一致
-
创建类,让这个类作为工厂bean,实现接口FactoryBean
-
实现接口的方法,在实现的方法中定义返回的bean类型
package com.lfh.spring.factorybean; import com.lfh.spring.collectiontype.Course; import org.springframework.beans.factory.FactoryBean; public class MyBean implements FactoryBean<Course> { //返回类型 @Override public Course getObject() throws Exception { Course course=new Course(); course.setCname("aaa"); return course; } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return false; } }
<?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 class="com.lfh.spring.factorybean.MyBean" id="myBean"></bean> </beans>
@Test public void testFactoryBean(){ //1.加载spring配置文件, ApplicationContext context=new ClassPathXmlApplicationContext("Factorybean.xml"); //2.获取配置文件创建对象, Course myBean = context.getBean("myBean", Course.class); System.out.println(myBean); }
-
-
-
IOC操作Bean管理(bean作用域)
-
在spring中可以设置bean的创建实例是单实例还是多实例
-
默认是单实例
@Test public void testStu(){ //1.加载spring配置文件, ApplicationContext context=new ClassPathXmlApplicationContext("StuBean.xml"); //2.获取配置文件创建对象, Stu stu = context.getBean("stu", Stu.class); Stu stu1 = context.getBean("stu", Stu.class); System.out.println(stu.equals(stu1)); }
-
设置多实例
<bean class="com.lfh.spring.collectiontype.Stu" id="stu" scope="prototype">
区别:
scope="prototype"设置为多实例,在调用getBean时,才会创建对象
scope="singleton"默认为单实例,加载spring配置文件时,就会创建对象
-
-
四、Bean生命周期(重点)
概念:从对象创建到对象销毁的过程
- 通过构造器创建bean实例(无参构造)
- 为bean的属性设置值和对其他bean的引用(调用set方法)
- 把bean实例传递给bean后置处理器(postProcessBeforeInitialization)
- 调用bean的初始化的方法(需要进行配置)
- 把bean实例传递给bean后置处理器(postProcessAfterInitialization)
- bean的使用(对象获取到了)
- 当容器关闭时候,调用bean的销毁方法(需要进行配置销毁方法)
后置处理器
-
创建类,实现接口BeanPostProcessor,创建后置处理器
package com.lfh.spring.beanlife; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPost implements BeanPostProcessor { /* */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return null; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return null; } }
<?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.lfh.spring.beanlife.User" init-method="initMethod" destroy-method="destoryMethod" > <property name="name" value="小白鼠"></property> </bean> <!--配置Post处理器--> <bean id="myBeanPost" class="com.lfh.spring.beanlife.MyBeanPost"> </bean> </beans>
五、xml自动装配
概念:更加指定的装配规则(属性名或者属性类型),Spring自动将匹配的属性值进行注入
-
演示自动装配
<!--实现自动装配--> <bean class="com.lfh.spring.autowire.Emp" id="emp" autowire="byName"> </bean>
<!--实现自动装配--> <bean class="com.lfh.spring.autowire.Emp" id="emp" autowire="byType"> </bean>
注意:autowire="byName"根据属性名称注入,注入值bean的id和类属性名称必须一致
autowire="byType"根据类型注入,不能有相同类型的bean
六、外部属性文件
场景:配置数据库信息
-
直接配置德鲁伊连接池
-
映入德鲁伊的jar包
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <!--驱动名称--> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql:3306/springboot" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean>
-
-
引入外部属性文件配置数据库
-
创建外部属性文件,properties格式文件,写数据库信息
diy.driverClassName=com.mysql.jdbc.Driver diy.url=jdbc:mysql:3306/springboot diy.username=root diy.password=123456
-
在xml中映入properties文件
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> </beans>
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--配置连接池--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <!--驱动名称--> <property name="driverClassName" value="${diy.driverClassName}" /> <property name="url" value="${diy.url}" /> <property name="username" value="${diy.username}" /> <property name="password" value="${diy.password}" /> </bean> <!--引入外部属性文件--> <context:property-placeholder location="druid.xml" /> </beans>
-
七、实现IOC操作Bean管理(基于注解)
注解概念(java基础笔记)
目的:简化xml配置
7.1 Spring针对Bean管理中创建对象提供注解
- @Componet
- @Service
- @Controller
- @Repository
四个注解功能都可以创建对象,只是便于开发者阅读
7.2 基于注解实现对象创建
-
引入aop依赖
-
开启组件扫描
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--开启组件扫描--> <context:component-scan base-package="com.lfh.annotation"/> </beans>
-
创建类,在类上添加注解
package com.lfh.spring.annotation.sercice; import org.springframework.stereotype.Component; @Component public class UserService { public void add(){ System.out.println("UserService add ..."); } }
7.3基于注解实现属性注入
-
@AutoWired:根据属性类型进行自动装配
-
@Qualifier:根据属性名称进行注入需要和@AutoWired一起使用,指定实现类
-
@Resoure:可以根据类型,也可以根据名称(java提供的)
package com.atguigu.spring5.service; import javax.annotation.Resource; //在注解里面value属性值可以省略不写, //默认值是类名称,首字母小写 //UserService -- userService //@Component(value = "userService") //<bean id="userService" class=".."/> @Service public class UserService { // @Resource 默认类型注入 //更具名称注入 @Resource(name = "userDaoImpl") private UserDao userDao; public void add() { System.out.println("service add......."); userDao.add(); } }
-
@Value:注入普通类型属性
7.4纯注解开发(SpringBoot)
-
创建配置类,替代xml配置文件
package com.atguigu.spring5.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /* 作为配置类 */ @Configuration @ComponentScan(basePackages = "com.atguigu.spring5") public class SpringConfig { }
-
编写测试类
@Test public void testService2() { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); userService.add(); }