一、耦合
1.概念:
程序间的依赖关系,包括类之间的依赖和方法间的依赖。
2.解耦:
降低程序之间的依赖关系。
实际开发中应该做到:编译器不依赖,运行期才依赖。
(报错发生在编译期,异常发生在运行期)
3.解耦的思路:
第一步:使用反射来创建对象,而避免使用new关键字。
(new创建的对象依赖具体的驱动类,反射创建的对象依赖的是字符串,这样就能降低耦合性,缺点是字符串不方便修改)
第二步:通过读取配置文件来获取要创建的对象的全类名
反射、序列化、克隆。
二、Spring框架的基础概念
1.什么是Spring:
Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。
2.spring 的优势:
1)方便解耦,简化开发
2)AOP 编程的支持
3)声明式事务的支持
4)方便程序的测试
5)方便集成各种优秀框架
6)降低 JavaEE API 的使用难度
3.spring 的体系结构:
三、Java的三层架构
1.业务层(service)调用持久层(dao),表现层调用业务层(servlet)
2.编写工厂类和配置文件
一个创建Bean对象的工厂
Bean:在计算机语言中,有可重用组件的含义。
JavaBean:用Java语言编写的可重用组件。JavaBean>实体类
它就是创建我们的service和dao对象的。
第一个:需要一个配置文件来配置我们的service和dao
配置内容:唯一标识=全类名(key=value)
第二个:通过读取配置文件中配置的内容,反射创建对象。
配置文件可以是xml也可以是properties(解析和读取相对简单)
bean.properties文件:
accouontService=com.anyi.service.impl.AccountServiceImpl
accountDao=com.anyi.dao.impl.AccountDaoImpl
三、IOC控制反转
1.百度百科给出的概念:
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
2.明确ioc的作用:
消减计算机程序的耦合(解除我们代码中的依赖关系)
3.普通三层架构与IOC模式对比
1)普通三层架构
private IAccountDao accountDao = new AccountDaoImpl();
由于我们是很多对象,肯定要找个集合来存。在应用加载时,创建一个 Map,用于存放三层对象。我们把这个 map 称之为容器。
我们在获取对象时,都是采用 new 的方式。是主动的。
2)工厂IOC模式
在获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。
这种被动接收的方式获取对象的思想就是控制反转,是spring的核心之一。
五、配置Spring框架需要的依赖
1.创建一个maven项目
2.在pom.xml文件中建立spring的依赖坐标:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
3.配置配置文件bean.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来管理-->
<bean id="accountService" class="com.anyi.service.impl.AccountServiceImpl"></bean>
<bean id="accountDao" class="com.anyi.dao.impl.AccountDaoImpl"></bean>
</beans>
遇到的报错信息:
URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs)
解决方法:
4.编写测试类获取核心容器对象、根据id获取bean对象
/**
* @description:模拟一个表现层,用于调用业务层(实际开发中是一个servlet)
**/
public class Client {
public static void main(String[] args) {
//IAccountService as = new AccountServiceImpl();
//1.获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//ApplicationContext ac = new FileSystemXmlApplicationContext("D:\\ideaProjects\\0908_spring2\\src\\main\\resources\\bean.xml");
//2.根据id获取bean对象
IAccountService as = (IAccountService)ac.getBean("accountService");
IAccountDao adao = ac.getBean("accountDao",IAccountDao.class);
System.out.println(as);
System.out.println(adao);
// as.saveAccount();
}
}
ApplicationContext的三个常用实现类
ClaPathXmlApplicationContext,它可以加载类路径下的配置文件,要求配置文件必须在类路径下,不在的话就加载不了(更常用)。
FileSystemXmlApplicationContext,它可以加载磁盘任意路径下的配置文件(必须有访问权限)
AnnotationConfigApplicationContext,它是用于读取注解创建容器
5.核心容器两个接口(ApplicationContext和BeanFactory)的区别
BeanFactory 才是 Spring 容器中的顶层接口。ApplicationContext 是它的子接口。
通常情况下子接口会对上层接口进行功能进行扩展,更加方便,更加智能。
1)ApplicationContext:使用于单例对象。它在构建核心容器时,创建对象采用的策略是采用立即 加载的方式,也就是说,只要一读取完配置文件,就马上创建配置文件中配置的对象。
1)BeanFactory:适用于多例对象。它在构建核心容器时,创建对象采取的策略是延迟加载的方式。也就是什么时候根据id获取对象了,什么时候才正真创建对象。
六、spring对bean对象的管理细节
service和dao都是bean对象。jar包中的类都是字节码文件,我们无法修改。
1.bean 标签及其属性:
1)作用:
用于配置对象让 spring 来创建的。
默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
2)属性:
id:给对象在容器中提供一个唯一标识。用于获取对象。
class:指定类的全类名。用于反射创建对象。默认情况下调用无参构造函数。
scope:指定对象的作用范围。
init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。
2.创建bean对象的三种方式:
(1)使用默认的构造函数创建。在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时,采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
<bean id="accountService" class="com.anyi.service.impl.AccountServiceImpl"></bean>
(2)使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
<bean id="instanceFactory" class="com.anyi.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccoountService"></bean>
(3)使用工厂中的静态方法创建对象(使用某个类中发静态方法创建对象,并存入spring容器)
<bean id="accountService" class="com.anyi.factory.StaticFactory" factory-method="getAccoountService"></bean>
3.bean的作用范围调整:
bean标签的scope属性:
作用:用于指定bean对象的作用范围
取值(常用的是单例的和多例的):
singleton:单例的,bean对象默认是单例的。
prototype:多例的
request:作用于web应用的请求范围
session:作用域于web应用的会话范围
global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
<bean id="accountService" class="com.anyi.service.impl.AccountServiceImpl" scope="singleton"></bean>
4.bean 的生命周期
spring框架是一个非常智能的框架,可以自动感知对象的作用范围(单例还是多例)从而给我们选择什么时候创建对象,是立即还是延迟加载。
1)单例对象
出生:当容器创建时出生
活着:只要容器存在,对象一直活着
死亡:容器销毁,对象死亡
总结:单例对象的生命周期和容器相同
2)多例对象
出生:当我们使用对象时spring框架为我们创建
活着:对象只要是在使用过程中就一直活着。
死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收