2.3 实现解耦
2.3.1 原始方案
public class UserServlet {
public static void main(String[] args) {
//要实现解耦:1.需要接口 需要多态 2.不能new实
现类对象
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
UserService userService=new
UserServiceImpl01();
userService.add();
}
}
public interface UserService {
public void add();
}
public class UserServiceImpl01 implements
UserService{
@Override
public void add() {
System.out.println("impl01...add...");
}
}
public class UserServiceImpl02 implements
UserService{
@Override
public void add() {
System.out.println("impl02...add...");
}
}
2.3.2 使用工厂类+反射进行解耦
public class BeanFactory {
public static UserService getUserServcie(){
return new UserServiceImpl01();
}
}
public class UserServlet {
public static void main(String[] args) {
//要实现解耦:1.需要接口 需要多态 2.不能new实
现类对象
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
//UserService userService=new
UserServiceImpl01();
//虽然解决了之前的耦合,但是引入的新的耦合:工厂
类和业务层存在耦合
UserService userService=
BeanFactory.getUserServcie();
userService.add();
}
}
public class BeanFactory {
// public static UserService getUserServcie()
{
// return new UserServiceImpl01();
// }
//负责创建实现类对象,不能使用new
//使用反射方式创建对象,方法接受实现类对象的全限定名
public static Object getBean(String
className){
try {
Class<?> clazz =
Class.forName(className);
return clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public class UserServlet {
public static void main(String[] args) {
//要实现解耦:1.需要接口 需要多态 2.不能new实
现类对象
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
//UserService userService=new
UserServiceImpl01();
//虽然解决了之前的耦合,但是引入的新的耦合:工厂
类和业务层存在耦合
//UserService userService=
BeanFactory.getUserServcie();
UserService userService= (UserService)
BeanFactory.getBean("com.lzw.service.UserService
Impl01");
userService.add();
}
}
2.3.3 使用工厂类+反射+配置文件解耦
- 导入依赖
<dependencies>
<!--DOM4j-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
- 编写beans.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="userService"
class="com.lzw.service.UserServiceImpl01">
</bean>
</beans>
- 编写工厂类
public class BeanFactory {
//定义Map集合 用于存储id和实现类对象
private static Map<String,Object> map=new
HashMap<>();
//加载并解析beans.xml文件 只需要加载一次
static {
try {
//加载beans.xml配置文件
SAXReader saxReader=new SAXReader();
InputStream in =
BeanFactory.class.getClassLoader().getResourceA
sStream("beans.xml");
Document document =
saxReader.read(in);
//解析beans.xml配置文件
Element beans =
document.getRootElement();//获取根标签beans
List<Element> beanList =
beans.elements();//获取子标签bean的集合
//遍历获取每一个bean标签
for (Element bean : beanList) {
//获取id 和 class 的属性的值
String idValue =
bean.attributeValue("id");
String classValue =
bean.attributeValue("class");
//通过反射创建对象 并存储到集合中
Object obj =
Class.forName(classValue).newInstance();
map.put(idValue,obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//提供一个方法, 用于从Map集合中, 获取指定id( 接口
字符串) 所对应的value( 接口实现类对象 )
public static Object getBean(String id){
return map.get(id);
}
}
public class UserServlet {
public static void main(String[] args) {
//要实现解耦:1.需要接口 需要多态 2.不能new实
现类对象
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
//UserService userService=new
UserServiceImpl01();
//虽然解决了之前的耦合,但是引入的新的耦合:工厂
类和业务层存在耦合
//UserService userService=
BeanFactory.getUserServcie();
//存在硬编码问题
//UserService userService= (UserService)
BeanFactory.getBean("com.lzw.service.UserService
Impl01");
UserService userService= (UserService)
BeanFactory.getBean("userService");
userService.add();
}
}
三.Spring IOC 相关概念
3.1 IOC 控制反转
IoC
(
Inversion Of Control
)控制反转,
Spring
反向控制应用
程序所需要使用的外部资源;
简单说,就是把创建创建对象的权力交给
Spring
去管理。
传统方式创建对象
: new
对象
(); (
主动创建
)
。当前类可以选
择主动出击(
new
的方式)创建对象,但是此时耦合度
高。
IOC
方式创建对象
:
找容器
(
被动接收
),
本质上就是一个
Map
集合。把主动式改成被动接收,由工厂对象为当前类生产
所必须的关联对象,此时降低了两个类的依赖关系。
3.2 SpringIOC容器介绍
Spring
控制的资源全部放置在
Spring
容器中,该容器称为
IOC
容器;
Spring
容器中存储的对象称为
bean
对象;
降低了组件之间的耦合性:
Spring IoC
容器通过依赖注入
机制,将组件之间的依赖关系削弱,减少了程序组件之间
的耦合性,使得组件更加松散地耦合。
提高了代码的可重用性和可维护性:将组件的实例化过
程、依赖关系的管理等功能交给
Spring IoC
容器处理,使
得组件代码更加模块化、可重用、更易于维护。
方便了配置和管理:
Spring IoC
容器通过
XML
文件或者注
解,轻松的对组件进行配置和管理,使得组件的切换、替
换等操作更加的方便和快捷。
交给
Spring
管理的对象(组件),方可享受
Spring
框架的
其他功能(
AOP,
声明式事务管理)等
3.3 SpringIOC容器接口和实现
BeanFactory
接口提供了一种高级配置机制,能够管理任
何类型的对象,它是
SpringIoC
容器标准化超接口!
ApplicationContext
是
BeanFactory
的子接口。添加了更多
特定于企业的功能。例如更容易与
Spring
的
AOP
功能集
成
ApplicationContext
容器实现类:
3.4 SpringIoC容器管理配置方式
Spring框架提供了多种配置方式:XML配置方式、注解方式和 Java配置类方式
SSM
期间,我们使用
XML+
注解方式为主
。
SpringBoot
期间,
我们使用
配置类
+
注解方式为主
!
四.基于XML的IOC环境搭建
1.
创建
Maven
工程
,
添加坐标
2.
准备好接口和实现类
3.
创建
spring
的配置文件
(applicationContext.xml),
配置bean标签
4.
创建工厂对象 获得
bean
调用
- 创建Maven工程, 添加坐标
<dependencies>
<!--导入spring的坐标spring-context,对应版
本是5.2.10.RELEASE-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springcontext</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
- 准备好接口和实现类
public interface UserService {
public void save();
}
public class UserServiceImpl implements
UserService{
@Override
public void save() {
System.out.println("service...save...");
}
}
- 创建spring的配置文件 (applicationContext.xml), 配置bean标签
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/bea
ns"
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xsi:schemaLocation="http://www.springframework.o
rg/schema/beans
http://www.springframework.org/schema/beans/spri
ng-beans.xsd">
<!--
bean标签:通过配置bean标签告诉IOC容器需要创建
的对象
id属性:bean的唯一标识,方便后期获取Bean
class属性:类的全类名!
-->
<bean id="userService"
class="com.lzw.service.UserServiceImpl"></bean>
</beans>
public class DemoTest {
@Test
public void test01(){
//创建IoC容器,并读取配置文件
ApplicationContext ioc =
new
ClassPathXmlApplicationContext("applicationConte
xt.xml");
//方式1:根据id获取 没有指定类型,返回为
Object,需要类型转化!
UserService userService01 =
(UserService) ioc.getBean("userService");
userService01.save();
//方式2:根据类型获取,但是要求,同类型只能有一个
对象交给IoC容器管理
UserService userService02 =
ioc.getBean(UserService.class);
userService02.save();
singleton(默认值):
含义:在 IOC 容器中,这个 bean 的对象始终为单实例
创建对象的时机:IOC 容器初始化时
prototype:
含义:这个 bean 在 IOC 容器中有多个实例
//方式3: 根据id和类型获取
UserService userService03 =
ioc.getBean("userService", UserService.class);
userService03.save();
}
}
五.Bean的相关配置
5.1 Bean的基础配置
<!--
bean标签:通过配置bean标签告诉IOC容器需要创建
的对象
id属性:bean的唯一标识,方便后期获取Bean
class属性:类的全类名!
-->
<bean id="userService"
class="com.lzw.service.UserServiceImpl"></bean>
5.2 Bean的作用域
-
singleton(默认值):
- 含义:在 IOC 容器中,这个 bean 的对象始终为单实例
- 创建对象的时机:IOC 容器初始化时
-
prototype :
-
含义:这个 bean 在 IOC 容器中有多个实例创建对象的时机:获取 bean 时如果是在 WebApplicationContext 环境下还会有另外两个作用域(但不常用):
-