Spring
官网:spring.io
-
Spring全家桶:
-
Spring Framework
-
Spring Boot
-
Spring Cloud
-
Spring Framework系统架构
Spring FrameWork 是Spring 生态中最基础的项目
-
Data Access:数据访问
-
Data Integration:数据集成
-
Web:Web开发
-
Aop:面对切面编程
-
Aspects: Aop思想实现
-
Core Container:核心容器
-
Test:单元测试于集成测试
核心概念
Ioc控制反转
使用对象时,有主动new产生对象转换为由外部提供对象,此过程中对象 创建控制权由程序转移到外部,此思想称为控制反转
spring提供一个容器,称为Ioc容器,用来充当Ioc思想中的“外部”
Ioc容器负责对象的创建,初始化等一系列工作,被创建或被管理的对象在Ioc容器中统称为Bean
DI 依赖注入
在容器中创立bean与bean之间的依赖关系的整个过程
最终效果
使用对象时不仅可以直接从Ioc容器中获取,并且获取到的bean已经绑定l所有的依赖关系
IoC入门案例
-
先导包pom.xml
-
定义Spring管理的类(接口)
-
创建配置文件 applicationContext.yml
//1.导入spring的坐标spring-context。 //2.配置bean //bean标签标示配置bean id属性标示给bean起名字 class属性表示给bean定义类型 <bean id="bookDao" clasee ="com.exapml.dao.impl.BookDaoImpl"/> <bean id="bookService" clasee ="com.exapml.Service.impl.BookServiceImpl"/>
//3.获取Ioc容器 ApplicationContext ctx = new ClassPathXmlApplictionConrext("applicationConstext.yml") //4.获取bean BookDao bookDao = (BoolDao) ctx.getBean("bookDap"); bookDao.save(); BookService bookService =ctx.getBean("bookService"); bookService.save();
DI入门案例
-
删除使用new的形式创建对象的代码
-
配置service与dao之间的关系
//5.删除业务层中使用new的方式创建的dao对象 一开始:private BookDao bookDao = new BookDaoImpl(); 删除后:private BookDao bookDao; //6.提供对象的set方法 public void setBookDao(BookDao bookDao){ this,bookDao = bookDao; } //7.配置server与dao的关系 property标签表示配置当前bean的属性 name属性表示配置哪一个具体的属性 ref属性表示参照哪一个bean <bean id="bookService" clasee ="com.exapml.Service.impl.BookServiceImpl"/> <property name="bookDao" ref="bookDao"/> </bean> //上面的ref里面的对当前容器bean里面的bookDao //name里面的对应的第五步属性的名称 <bean id="bookDao" clasee ="com.exapml.dao.impl.BookDaoImpl"/>
bean配置
基本配置
id:bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id值唯一
class:bean的类型,即配置的bean的全路径类名
BookDao bookDao = (BoolDao) ctx.getBean("bookDap"); bookDao.save(); BookService bookService =ctx.getBean("bookService"); bookService.save();
bean别名配置
//name属性中,可以建多个别名,用,空格;进行分隔 <bean id="bookService" name="service,service2" clasee ="com.exapml.Service.impl.BookServiceImpl"/> <property name="bookDao" ref="bookDao"/> </bean>
bean作用范围配置
//可以通过属性scope来控制创造出来的对象是不是单例对象,默认为单例 <bean id="bookDao" clasee ="com.exapml.dao.impl.BookDaoImpl" scope="prototype"/>//已经不是单例
-
适合给容器进行管理的bean
-
表现出对象 save
-
业务层对象 service
-
数据层对象 do
-
工具对象
-
-
不适合给容器进行管理的bean
-
分装实体的域对象
-
bean实例化
-
使用无参构造方法(常用)
-
使用静态工厂
-
实例工厂(先配置一个工厂bean)
-
FactoryBean实例化(很重要)
bean生命周期
bean从创建到销毁的完整过程
-
使用配置(init-method=“init” destroy-method=“destroy”)
-
使用接口
初始化容器
-
创建对象(内存分配)
-
执行构造方法
-
执行属性注入(set操作)
-
执行bean初始化方法
使用bean
执行业务操作
关闭/销毁容器
执行bean销毁方法
-
手动关闭容器 close()
-
注册关闭钩子 registerShutdownHook()
bean延迟加载
但lazy-init设置为true时为延迟加载,就是当Spring容器创建的时候,不会立即创建Bean实例,等待用到时在创建Bean实例并存储到单例池中去,后续在使用该Bean直接从单例池获取即可,本质上Bean还是单例
依赖注入
bean运行时需要的类型:
setter注入
-
引用类型
//setter注入需要提供要注入对象的set方法 public void setUserDao(UserDao userDao) { this.userDao = userDao; } //setter注入需要提供要注入对象的set方法 public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } public void save() { System.out.println("book service save ..."); bookDao.save(); userDao.save(); }
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"> <!--property标签:设置注入属性--> <!--name属性:设置注入的属性名,实际是set方法对应的名称--> <!--ref属性:设置注入引用类型bean的id或name--> <property name="bookDao" ref="bookDao"/> <property name="userDao" ref="userDao"/> </bean>
-
简单类型(基本数据类型与String)
-
在bean中定义引用类型属性并提供可访问的set方法
-
使用propertry标签value属性注入简单类型数据
private int connectionNum; //setter注入需要提供要注入对象的set方法 public void setConnectionNum(int connectionNum) { this.connectionNum = connectionNum; }
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <!--property标签:设置注入属性--> <!--name属性:设置注入的属性名,实际是set方法对应的名称--> <!--value属性:设置注入简单类型数据值--> <property name="connectionNum" value="100"/> </bean>
-
构造方法注入(构造器)
-
简单类型
-
引用类型
-
在Bean中定义引用类型属性并提供可访问的构造方法
public class BookServiceImpl implements BookService{ private BookDao bookDao; public BookServiceImpl(BookDao bookDao){ this.bookDao = bookDao; } }
-
配置中使用constructor-arg标签ref属性注入引用类型对象
-
<bean id="bookService" class=""> <constructor-arg name="bookDao" ref="bookDao"/> </bean> <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
依赖注入方式选择
-
强制依赖使用构造器进行,setter注入有概率不进行注入导致null对象出现
-
可选依赖使用setter注入进行,灵活性强
-
Spring框架使用构造器,第三方内部大多数采用构造器注入的形式进行数据初始化,相对严谨
-
有必要可以两者同时使用
-
实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
-
自己开发的模块使用setter注入
依赖自动装配
-
按类型
<bean class="com.itheima.dao.impl.BookDaoImpl"/> <!--autowire属性:开启自动装配,通常使用按类型装配--> <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
-
按名称
特征
-
用于引用类型依赖注入,不能对简单类型进行操作
-
使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
-
使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
-
自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
集合注入
-
List
-
array
-
map
-
properties
-
set
案例:数据源对象管理
-
管理DruidDataSource对象
-
引入依赖
-
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
-
数据库的连接
<bean id="dataSource" class="com.alibaba.druid.pool,DruidDataSource"> //setter注入 <property name="driverClassName" value="com.mysql.jdbc.Driver"> <property name="url" value="jdbc:mysql://localhost:3306/xdb"> <property name="username" value="root"> <property name="password" value="123456"> </bean>
-
c3p0的连接池
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/xdb"/> <property name="user" value="root"/> <property name="password" value="123456"/> //最大连接数 <property name="maxPoolSize" value="100"/> </bean>-->
Spring管理第三方资源
1.DruidDataSource
2.ComboPooledDataSource
加载properties文件
-
开启命名空间(context)
<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空间加载properties文件
<context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/> //system-properties-mode="NEVER",表示系统属性不加载 //加载多个配置文件 <context:property-placeholder location="jdbc.properties,jdbc.properties2" system-properties-mode="NEVER"/> //加载全部的配置文件 <context:property-placeholder location="*.properties" system-properties-mode="NEVER"/> //规范格式(只能读取当前项目配置的文件) <context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/> //规范格式(可以读取从类路径或jar包中搜索并加载的配置文件) <context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
-
使用属性占位符${}读取properties文件中的属性
<bean class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean>
核心容器(ApplicationContext)
-
加载类路径的配置文件(用这种)
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
-
从文件系统加载配置文件
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\workspace\\spring\\spring_10_container\\src\\main\\resources\\applicationContext.xml");//用配置文件的绝对路径
-
bean加载的格式
//通过名称获取 BookDao bookDao = (BookDao) ctx.getBean("bookDao"); //通过名称来获取,再加一个类型 BookDao bookDao = ctx.getBean("bookDao",BookDao.class); //不能有多个bean,用类型查找 BookDao bookDao = ctx.getBean(BookDao.class);
-
容器类层次结构图
-
BeanFactory初始化(了解)
所有容器类的顶层接口
创建完毕后,所有的bean均为延迟加载
注释开发(重点,简化开发)
注解开发定义bean
1.使用@Component定义bean
@Component("bookDao") public class BookDaoImpl implements BookDao { } @Component public class BookServiceImpl implements BookService{ }
2.核心配置文件中通过组件扫描bean
<context:component-scan base-package="com.itheima"/>
-
Spring提供@Component·注解的三个衍生注解
-
@controller:用于表现层bean定义
-
@Service:用于业务层bean定义
-
@Repository:用于数据层bean定义
-
-
调用方法
//按名称 BookDao bookDao = (BookDao) ctx.getBean("bookDao"); System.out.println(bookDao); //按类型获取bean BookService bookService = ctx.getBean(BookService.class); System.out.println(bookService);
纯注解开发
-
新建一个类
-
@Configuration //用来声明当前类为Spring配置类 (配置文件的结构==@Configuration)
-
@ComponentScan({"com.itheima.service","com.itheima.dao"}) //设置bean扫描路径,多个路径书写为字符串数组格式 (这个是可以多个需要变成数组的格式,单个的格式就是不需要大括号,只能放一个路径)
-
新建一个启动类(用于纯注解开发)
//以前加载配置文件 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //加载配置类 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); //其他一样 //按名称 BookDao bookDao = (BookDao) ctx.getBean("bookDao"); System.out.println(bookDao); //按类型获取bean BookService bookService = ctx.getBean(BookService.class); System.out.println(bookService);
bean管理
bean作用范围
@Scope("prototype")//非单例 @Scope("singleton")//单例(可写可不写,默认单例)
bean生命周期
//构造后的方法 @PostConstruct public void init() { System.out.println("init ..."); } //彻底销毁前的方法 @PreDestroy public void destroy() { System.out.println("destroy ..."); }
因为spring默认为单例,如果执行非单例时,Spring就不会再管bean的生命周期了
依赖注入
自动装配
//@Autowired:注入引用类型,自动装配模式,默认按类型装配 //不需要set方法,因为自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据 //自动装配默认使用无参构造方法,如果不提供对应构造方法,请提供唯一的构造方法 @Autowired //@Qualifier:自动装配bean时按bean名称装配 @Qualifier("bookDao") private BookDao bookDao; public void save() { System.out.println("book service save ..."); bookDao.save(); }
加载properties文件
//@Value:注入简单类型(无需提供set方法) //注入的值 @Value("123456") //外部配置文件 @Value("${name}") private String name; public void save() { System.out.println("book dao save ..." + name); } 需要在配置类里面加 @Configuration @ComponentScan("com.itheima") //@PropertySource加载properties配置文件 @PropertySource({"jdbc.properties"}) public class SpringConfig { }
第三方Bean管理
第三方bean管理
-
第三方bean可以写在专属的Spring的类下,只是会很混乱
public class SpringConfig{ //1.定义一个方法活动管理的对象 //2.添加@Bean表示单曲方法的方法返回值是一个bean @Bean public DataSource dataSource() { DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/xdb"); ds.setUsername("root"); ds.setPassword("123456"); return ds; } }
-
导入式(将独立的配置类加入核心配置)
-
使用@Import注解手动加入配置类到核心配置,此注解只能添加一次,多个需要加{}
public class JdbcConfig{ @Bean public DataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/xdb"); ds.setUsername("root"); ds.setPassword("123456"); return ds; } } @Configuration @Import(JdbcConfig.class) public class SpringConfig{ }
第三方bean注入
-
简单依赖注入
public class JdbcConfig { //1.定义一个方法获得要管理的对象 @Value("com.mysql.jdbc.Driver") private String driver; @Value("jdbc:mysql://localhost:3306/spring_db") private String url; @Value("root") private String userName; @Value("root") private String password; //2.添加@Bean,表示当前方法的返回值是一个bean //@Bean修饰的方法,形参根据类型自动装配 @Bean public DataSource dataSource(){ System.out.println(bookDao); DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; } }
-
引用类型
//方法形参 @Bean public DataSource dataSource(BookDao bookDao){ System.out.println(bookDao); DruidDataSource ds = new DruidDataSource(); return ds; }
注解开发总结
XML配置与注解配置比较