目录
5. BeanFactory和ApplicationContext
1. 什么是Spring
1. Spring是一个轻量级开源的JAVAEE框架。
2. Spring提高了IOC和AOP
IOC:控制反转。把创建java对象的权力交于spring容器来管理。
AOP:面向切面编程.在不改变源代码的前提下可以扩充功能。
3. spring的特点:
方便解耦,简化开发----层层之间的依赖降低。
声明式事务的支持:
方便程序的测试:----提供单元测试jar,
方便集成各种优秀框架---集成第三方的框架---mybatis
2. 程序的耦合
2.1 什么是耦合
Spring有一个特点便是解耦,那么什么是耦合呢
耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。
分类有内容耦合、公共耦合 、 外部耦合 、控制耦合 、标记耦合 、数据耦合 、非直接耦合
耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。
2.2 实例
有一个Food类,其他类需要调用该类,那么使用Food food = new Food()进行创建,但是如果Food类发生改变(升级变为TastyFood),那么其他类便也需要改编为 TastyFood tf = new TastyFood();这便是耦合性太高,如果调用Food的类是大量的,那么大量的类要修改。
//为方便例子写在一个类里面了
class Food{
private String name;
}
class test1{
private Food food = new Food();
}
class test2{
private Food food = new Food();
}
class test3{
private Food food = new Food();
}
我们可以手动的进行解决,这一过程为解耦
class Food{
private String name;
}
//增加一个FoodFactory类,用于返回Food
class FoodFactory{
public static Food getFood(){
return new Food();
}
}
class test1{
private Food food = FoodFactory.getFood();
}
class test2{
private Food food = FoodFactory.getFood();
}
class test3{
private Food food = FoodFactory.getFood();
}
使用工厂模式,创建一个FoodFactory类对Food对象进行生产,但是并没有解决问题,如果Food类名发生改变,Food food 中的类定义依旧需要改变。
interface IFood{
}
class Food implements IFood{
private String name;
}
//增加一个FoodFactory类,用于返回Food
class FoodFactory{
public static IFood getFood(){
return new Food();
}
}
class test1{
private IFood food = FoodFactory.getFood();
}
class test2{
private IFood food = FoodFactory.getFood();
}
class test3{
private IFood food = FoodFactory.getFood();
}
可以看到,我们创建了一个IFood接口,让Food实现该接口,运用多态,FoodFactory中返回的接口类型,而其他类调用时候,也用接口接收,那么,不管Food怎么改变,其他的代码都不要改变。
以上是我们手动解耦,肯定有许多考虑欠缺的地方,那么有没有现成的框架帮你完成对象与对象之间的解耦呢? 有----spring框架。
3. IOC控制反转
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
使用对象的时候不再是我们直接new,而是将创建对象的权利交给框架中的核心容器IOC,需要使用对象的时候直接从容器中获取。
IoC的思想早就出现了, Rod Johnson(Spring Framework创始人)写了一个框架,将IoC思想具体的实现了,这个框架后来起了个名字叫做 Spring(因为在这之前 大家都是用hibernate这个框架,这个框架中文名字叫做冬眠,并且这个框架比较笨重,耦合比较高。Rod Johnson写的框架就是用来解决类似于hibernate高耦合的问题 ,所以他将自己框架的名字命名为 Spring 告诉全世界 冬天过去了 春天来了 )
4. Spring的使用
(1)引入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
</dependencies>
(2)在Resources下创建Spring配置文件(一般命名为applicationContext.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">
<!--表示一个类交于spring容器来创建
id:bean的唯一标识。
class: 类的全路径
-->
<bean id="userDao" class="com.aaa.UserDao"></bean>
</beans>
(3)创建Dao类
public interface IUserDao {
public void show();
}
public class UserDao implements IUserDao {
public void show(){
System.out.println("show方法被调用");
}
}
(4) 测试类
package com.lcy.test;
import com.lcy.service.IUserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author Lcy
* @Date 2022/6/11
*/
public class UserDaoTest {
@Test
public void testUserDao(){
//读取配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean对象
IUserDao userDao = (IUserDao) ac.getBean("userDao");
userDao.show();
}
}
5. BeanFactory和ApplicationContext
5.1 BeanFactory接口
Spring容器顶层接口,获取Bean对象,管理类和类之间的关系(依赖关系)。BeanFactory由org.springframework.beans.factory.BeanFactory接口定义 BeanFactory是工厂模式(Factory pattern)的实现,是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
@Test
//BeanFactory 懒汉式,只有使用bean时才会创建该bean
public void testBeanFactory(){
//读取配置文件
ClassPathResource resource = new ClassPathResource("applicationContext.xml");
//解析配置文件
XmlBeanFactory factory = new XmlBeanFactory(resource);
Object userDao = factory.getBean("userDao");
Object student = factory.getBean("student");
}
5.2 ApplicationContext接口
ApplicationContext接口是基于BeanFactory之上的,提供了应用程序框架服务,扩展的新功能如下:提供国际化的支持资源访问,如URL和文件 事件传递载入多个配置文件等 实现类常见有三个
ClassPathXmlApplicationContext:-classpath路径加载xml文件的
FileSystemXmlApplicationContext:基于项目根路径进行加载xml文件的
AnnotationConfigApplicationContext:基于注解的配置。基于类书写的配置。
@Test
//ApplicationContext 饿汉式,一旦读取spring配置文件,便会创建配置bean
public void testApplicationContext(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Object userDao = ac.getBean("userDao");
Object student = ac.getBean("student");
}
5.3 区别
面试题:BeanFactory 和 ApplicationContext 的区别:
BeanFactory 才是 Spring 容器中的顶层接口。
ApplicationContext 是它的子接口。
单例模式下创建对象的时间点不一样:
ApplicationContext:(饿汉模式)只要一读取配置文件,马上就会创建配置文件中配置的对象。
BeanFactory:(懒汉模式)什么时候getBean("id"),也就是说当根据id获取对象时,才会创建。
6. 获取bean的方式
1. 通过bean.xml文件中bean标签的id的值获取bean(使用默认构造方法)
//根据bean的id获取Bean对象,强制转换.
IUserDao iUserDao= (IUserDao) ac.getBean("userDao");
2. 通过类型去获取
IUserDao userDao = ac.getBean(IUserDao.class); //通过类型获取bean对象。
3. 前两者结合(第一种需要手动强制转换类型,第二种需要确保bean的类型唯一,不然会报错:org.springframework.beans.factory.NoUniqueBeanDefinitionException )
IUserDao userDao = ac.getBean("userDao", IUserDao.class);
7. bean的作用范围
bean中有一个属性scope,可以设置时单例(得到的是同一个实例)还是多例(每次创建都会返回新的实例),ApplicationContext接口来说,默认是单例的
scope可以设置有4个值
singleton:单例的(默认值)当加载配置文件时,就会创建对象。
prototype:多例的(当getBean时才会创建对象)
request:作用于请求范围---同一个那么使用bean同一个。
session:作用于会话范围---同一个会话那么使用bean同一个。