文章目录
Spring技术
初步认识Spring
- 简化技术:降低企业的级开发的复杂性
- 框架整合:高效整合其他技术,提高企业级应用开发与运行效率
- Spring官网:http://spring.p2hp.com/quickstart.html 帮助我们了解学习
- Spring全家桶:
- Spring Framework—框架:其他技术都是依赖它
- Spring MVC:web开发
- Spring Boot:加速Spring的开发,提高开发速度,书写更少的代码
- Spring Cloud:分布式开发技术
- ……
Spring Framework系统架构
Spring架构图的发展,4.x已经趋于稳定:
分析4.X的构架图:
- Core Container–管理对象的
- 构架的上层依赖下层
- Spring技术包容其他技术,可以和其他技术整合
一、Spring IoC(IoC/DI)
概念:控制反转(Inversion of Control,IoC),也称为依赖注入(Dependency Injection),是面向对象编程中的一种涉及理念,用来降低程序代码之间的耦合度。
通俗语言讲解一下IoC的过程:------------------------
IoC控制反转
以前我们在写数据实现层和业务实现层的时候要使用-----接口new实现,代码耦合度偏高。【HouseDao houseDao = new HouseDaoImpl()等方式不在使用,将会放在IoC容器中】
解决使用IoC:使用对象时,不在程序中主动new产生对象,转换为由外部
提供对象,此过程中对象创建控制权
由程序转移到外部,此思想成为控制反转。
IoC容器:Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的“外部”
。
IoC容器负责对象的创建、初始化等一系列工作,被创建或者管理的对象在IoC容器中统称为Bean
。
DI依赖注入
我们将service和dao对象放入容器中,但在代码使用中,service的实现依赖dao对象运行,所以Spring的IoC容器将依赖也绑定了,此过程的专业术语就叫做依赖注入
.
DI依赖注入:在容器中建立Bean与Bean之间的依赖关系的过程。
案例
项目是建立在dao层,daoImpl实现,service层,serviceImpl实现和测试结构中
//dao层接口:
public interface UserDao {
public void save(User user);
}
//dao层实现
public class UserDaoImpl implements UserDao {
public void save(User user) {
System.out.println("保存用户信息到数据库");
}
}
//service接口
public interface UserService {
public void addNewUser(User user);
}
//service实现类
public class UserServiceImpl implements UserService {
private UserDao dao = new UserDaoImpl();
public void addNewUser(User user) {
// 调用用户DAO的方法保存用户信息
dao.save(user);
}
}
①IoC:
第一步:pom.xml关于Spring的坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
第二步:配置文件applicationContext.xml
导入坐标才会有Spring的配置文件,或者直接创建一个空白的xml文件去文档找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 -->
<!-- bean标签配置bean,id属性给bean起名字,class属性给bean定义类型 -->
<bean id="userDao" class="包名.UserDaoImpl"/>
<bean id="userService" class="包名.UserServiceImpl"/>
</beans>
第三步:测试类创建容器、获取bean:
【创建容器的两种方式都可以加载多个配置文件;获取bean的三种方式】
【代码:】
public class test{
public static void main( String[ ] args) {
//加载配置文件得到上下文对象,也就是容器对象
ApplicationContext ctx = new ClassPathXmlApplicationcontext("applicationContext.xml")
//获取资源getBean()
// UserDao userDao = (UserDao ) ctx.getBean("userDao");
// 执行方法
UserService userService = (UserService) ctx.getBean("userService");
执行方法
}
}
②DI:
完成IoC之后依赖注入的步骤:
- 1.基于IoC管理bean
- 2.Service中使用的new形式创建的Dao对象不在保留
- 3.提供方法使Service中需要的Dao对象进到Service中
- 4.配置Service与Dao的关系描述
第四步:改变业务层的new对象
//service实现类
public class UserServiceImpl implements UserService {
//删除业务层中使用new的方法创建的dao对象
private UserDao userdao ;
//提供对应的set,get方法
public UserDao getUserDao() {
return userdao;
}
public void setUserDao(UserDao userdao ) {
this.userdao = userdao ;
}
public void addNewUser(User user) {
// 调用用户DAO的方法保存用户信息
dao.save(user);
}
}
第五步:配置service与dao的关系
<!-- 配置bean -->
<bean id="userDao1111" class="com.jules.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.jules.service.impl.UserServiceImpl">
<!-- property标签表示配置当前bean的属性 -->
<!-- name属性对应private UserDao userdao的属性; -->
<!-- ref属性表示当前容器中bean标签中的id的名字userDao1111 -->
<property name="userDao" ref="userDao1111" />
</bean>
Bean配置
bean的基础配置:id、class
bean的别名配置:name
name属性:
1.有id属性的情况下,这时name不是第一标识符,那么name的所有值都是别名,别名之间用逗号隔开;
2.仅设置name属性,那么name就是bean的唯一标识符,不是别名。
- 给dao的bean对象起别名,在ref中也可以使用
<bean id="userDao1111" name="dao" class="com.jules.dao.impl.UserDaoImpl"/>
<bean id="userService" name="service,service1" class="com.jules.service.impl.UserServiceImpl">
<property name="userDao" ref="dao" />
</bean>
- 给service的bean对象起别名,测试类中获取资源就可以用name属性中的别名
//测试类获取资源那一步骤:
UserService userService = (UserService) ctx.getBean("service");
注意:NoSuchBeanDefinitionException异常
获取bean无论是通过 id 还是 name 获取,如果无法获取到,将抛出NoSuchBeanDefinitionException
NoSuchBeanDefinitionException: No bean named 'service888' available
此时要么测试类的getBean(“”)中写错,就是xml配置中名字写错,检查。
bean的作用范围:scope
Spring默认给我们创建的bean是单例模式
//测试类中打印:一个bean的两个对象输出的地址是一样的,证明是单例
public class test{
public static void main( String[ ] args) {
//加载配置文件得到上下文对象,也就是容器对象
ApplicationContext ctx = new ClassPathXmlApplicationcontext("applicationContext.xml")
UserService userService1 = (UserService) ctx.getBean("use rService");
System.out.print(userService1);
UserService userService2 = (UserService) ctx.getBean("userService");
System.out.print(userService2);
}
}
思考:如何创建非单例模式呢?
在bean标签中有属性scope可以控制一个bean创造的两个对象是否是同一个对象
scope功能:定义bean的作用范围,可选范围如下:
- singleton:单例(默认)
- propotype:非单例
范例:<bean id="userDao1111" name="dao" class="com.jules.dao.impl.UserDaoImpl" scope="prototype"/>
并不是所有的bean创建的对象都适合单例模式
适合交给容器进行管理的bean【造一次多次使用】
- 表现层对象----servlet
- 业务层对象----service
- 数据层对象----dao
- 工具对象---- 工具封装
不适合交给容器进行管理的bean【每次封装的数据不同】
- 封装实体的域对象-----特点:类中会记录一些成员变量的属性值