Spring
一、Spring概述
Spring是分层的Java SE/EE应用full-stack(全栈式)轻量级开源框架
full-stack(全栈式):对各种主流技术和框架都进行了整合,对三层架构都提供了解决方案
轻量级:轻量级和重量级的划分主要依据是看他使用了多少服务,启用时需要加载的资源多少以及耦合度等等
两大核心:
IOC:控制反转,把对象的创建权交给spring
AOP:面向切面编程,在不修改源码的情况下,对方法进行增强。
spring优势:
- 方便解耦,简化开发。耦合:程序间的依赖关系,解耦:降低程序间的依赖关系(体现:编译器不依赖,运行期才依赖)。
- AOP编程的支持,可以在不修改源码情况下,对方法进行增强。面向切面编程。
- 声明式事务的支持:通过配置事务完成原理,无需手动编程
- 方便测试,降低JavaEE API的使用
- 方便集成各种优秀框架
Spring坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
Spring核心配置文件
applicationContext.xml
//约束头文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--
在spring配置文件中配置UserImpl
id: 唯一标识
class:类全路径
-->
<bean id = "userDao" class = "com.wangfei.dao.impl.UserDaoImpl"></bean>
生成约束头文件后,只要连网,就会提示。
如果有多个bean标签,id值是不能重复的;要生成UserDaoImp,就在class里写实现类的全路径,Spring的底层是通过反射,根据类全路径生成实例对象。
使用Spring相关API获得bean实例:
SpringTest类:
\\测试方法
@Test
public void test1(){
//获取到了Spring上下文对象,借助上下文对象可以获取到IOC容器中的bean
ApplicationContext classPathApplication = new ClassPathXmlApplicatonContext("applicationContext.xml")//参数是核心配置文件的类全路径
//使用上下文对象从IOC容器中获取到bean对象。
IuserDao userDao = (IUSerDao)classPathXmlApplicationContext.getBean("userDao") //传递的参数是Bean的id值
//调用方法
userDao.save();
}
Application是一个接口,ClassPathXmlApplicatonContext()是一个实现类
通过Spring核心配置文件进行解析,通过类全路径反射,生成该类的实例对象,ClassPathXmlApplicatonContext里的参数,加载配置文件,并且对配置文件的bean标签进行解析,获取到bean标签中class的类全路径,使用反射生成该类对象,生成该类的实例对象,结合id最后生成到Spring的IOC容器中,接着就获取IOC中的bean对象
知识小结
- 导入坐标
- 创建Bean
- 创建applicationContext.xml
- 在配置文件中进行Bean配置
- 创建ApplicationContext对象,执行getBean
Spring 相关API
BeanFactory
public void test2(){
//核心接口,不会创建bean对象存到容器中
BeanFactory xmlBeanFactory = newXmlBeanFactory(new ClassPathResourse("applicationContext.xml"));
//getBean的时候才会真正创建bean对象
IUserDao userDao = (IUserDao) xmlBeanFactory.getBean("userDao");
userDao.save();
}
ApplicationContext和BeanFactory区别:
BeanFactory在第一次调用getBean时,才创建Bean对象;
ApplicationContext classPathApplication = new ClassPathXmlApplicatonContext(“applicationContext.xml”)在创建实现类对象时,同时就创建了Bean对象存到容器中,从容器中getBean,获取到参数。
ApplicationContext
常用实现类:
ClassPathXmlApplicatonContext: 从类的根路径下加载配置文件,推荐使用
FileSystemXmlApplicationContext:从磁盘路径上加载核心配置文件,磁盘文件可以在磁盘的任意位置
AnnotationConfigApplicationContext:当使用注解配置容器时,需要使用此类创建Spring容器,它用来读取注解。
AnnotationConfigApplicationContext annotationConfigApplicationContext = new ClassPathXmlApplicatonContext("applicationContext.xml");
常用方法:
1. Object getBean(String name);
根据Bean的id从容器中获得Bean实例,返回值object,需要强转
2. <T> T getBean(Class<T> requireType)
IUserDao userDao = classPathXmlApplicationContext.getBean(IUserDao.Class)
根据类型在容器中进行查询:有可能报错的情况:当前类型匹配到多个实例
3. <T> T getBean(String name,Class<T> requireType)
IUserDao userDao = classPathXmlApplicationContext.getBean("userDao",IUserDao.Class)
根据类型和Bean的id在容器中进行查询,解决匹配到多个实例的问题
Spring核心配置文件
-
Bean配置
<bean id = "" class = ""></bean> 用于配置对象交由Spring来创建 id: 唯一标识 class:类全路径 默认情况下,他调用的时类中的无参构造,如果没有无参构造,则不能创建成果
-
Bean标签范围配置
<bean id = "" class = "" scope = ""></bean>
scope属性指对象的作用范围,取值如下
取值范围 说明 singleton 默认值,单例模式 prototype 多例 request Web项目中,Spring创建一个Bean对象,将对象创建到request域中 session Web项目中,Spring创建一个Bean对象,将对象创建到session域中 global session Web项目中,应用Portlet环境,如果没有Portlet环境,那么globalSession相当于session 1.当scope取值为singleton时 Bean的实例化对象个数:1个 Bean实例化实际,当Spring核心文件被加载时,实例化配置的Bean实例 Bean的生命周期: 对象创建:当应用加载,创建容器时,对象就被创建了 对象运行:只要容器在,对象一直活着 对象销毁:当应用卸载,销毁容器时,对象就被销毁 2.当scope取值为prototype时 Bean的实例化个数:多个 Bean实例化实际:当调用getBean()方法时实例化Bean Bean的生命周期: 对象创建:当使用对象时,创建新的对象实例(getBean) 对象运行:只要兑现在使用中,就一直活着 对象销毁:当对象长时间不使用时,被Java的垃圾回收器收回
-
Bean生命周期配置
<bean id = "" class = "" scope = "" init-method="" dedstory-method=""></bean>
init-method=“” 指定类中的初始化方法名称
destory-method=""指定类中销毁方法名称
Bean依赖注入
依赖注入 DI(Dependency Injection):时Spring框架核心IOC的具体体现。
在编写程序时,通过控制反转,把对象的创建交给Spring,但是代码中不可能没有依赖的情况,IOC解耦只是降低了他们的依赖关系,但不会消除,例如:业务层仍会调用持久层的方法。
那么重者业务层和持久层的依赖关系,在使用Spring之后,就让Spring来维护,简单的说,就是通过框架把持久层对象传到业务层,不用我们自己获取。
Bean依赖注入方式:
-
构造方法注入
在UserServiceImpl中创建有参构造
public class UserServiceImpl implenments UserService{ private UserDao userDao; this.userDao = userDao; } @Override public void save(){ userDao,save(); }
配置Spring容器调用有参构造时进行注入
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl"></bean> <bean id = "userService" class = "com.wf.service.impl.UserServiceImpl"> <!--<constructor-arg index = "0" type = "com.wf.dao.UserDao" ref = "userDao"/>--> <constructor-arg name ="userDao" ref ="userDao"></constructor-arg> </bean>
<constructor-arg>标签是有参构造的标签 index属性: 给UserviceImpl有参构造第一个参数赋值。 type : 类型 ref: 表示引用,引用IOC的哪个对象注入到参数中
-
set方法注入
通过set方法注入实例对象,
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl"></bean>
<bean id = "userService" class = "com.wf.service.impl.UserServiceImpl">
<property name = "userDao" ref ="userDao"></property>
</bean>
name的参数为set方法传入的对象名,ref引用对象,找到实例对象,注入给userDao属性
-
p命名空间注入
本质也是set注入,比set方法更简单。
- 首先引入p命名空间
xmlns="http://www.springframework.org/schema/p"
-
其次,需要需改注入方式:
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl"></bean> <bean id = "userService" class = "com.wf.service.impl.UserServiceImpl" p:userDao-ref = "userDao"></bean>
类型注入
普通类型注入:(采用set方法注入,在UserDaoImpl类中添加set方法)
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl">
<property name = "username" value = "张飞"></property>
<property name = "age" value ="18"></property>
</bean>
ref用于引用数据类型的注入,value用于普通数据类型的注入
list集合注入:(采用set方法注入,在UserDaoImpl类中添加set方法)
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl">
<property name = "list" >
<list>
<value>aaa</value>
</list>
</property>
</bean>
set集合注入:
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl">
<property name = "set" >
<set>
<value>aaa</value>
</set>
</property>
</bean>
Array数组注入:
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl">
<property name = "array" >
<array>
<value>aaa</value>
</array>
</property>
</bean>
Map集合注入:
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl">
<property name = "map" >
<map>
<entry key = "k1" value = "ddd"></entry> //普通数据类型
<entry key = "k2" value-ref = "user"></entry>//引用数据类型
</mapy>
</property>
</bean>
property数据类型注入:
<bean id = 'userDao' class = "com.wf.dao.impl.UserDaoImpl">
<property name = "property" >
<pros>
<prop key = "k1">v1</porp> //普通数据类型
<prop key = "k2">v2</prop>//引用数据类型
</prop>
</property>
</bean>
配置文件模块化
实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分
配置拆解到其他配置文件中,也就是所谓的配置文件模块化。
-
并列的多个配置文件
ApplicationContext act = new ClassPathXmlApplicationContext("beans1.xml","beans2.xml","...");
-
主从配置文件
在applicationContext文件中加载其他配置文件 <import resource="applicationContext-xxx.xml"/>
注意:
-
同一个xml中不能出现相同名称的bean,如果出现会报错
-
多个xml如果出现相同名称的bean,不会报错,但是后加载的会覆盖前加载的bean
-
知识小结:
<bean>标签:创建对象并放到spring的IOC容器
id属性:在容器中Bean实例的唯一标识,不允许重复
class属性:要实例化的Bean的全限定名
scope属性:
Bean的作用范围,常用是Singleton(默认)和prototype
<constructor-arg>标签:属性注入有参构造
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值
<property>标签:属性注入
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值
<list>
<set>
<array>
<map>
<props>
<import>标签:导入其他的Spring的分文件