Spring 简介
1、Spring 是轻量级的开源的 JavaEE 框架
(轻量级:依赖少,文件小)
2、Spring 可以解决企业应用开发的复杂性
3、Spring 有两个核心部分:IOC 和 Aop
(1)IOC:控制反转,把创建对象过程交给 Spring 进行管理
(2)Aop:面向切面,不修改源代码进行功能增强
4、Spring 特点
(1)方便解耦,简化开发
(2)Aop 编程支持
(3)方便程序测试
(4)方便和其他框架进行整合
(5)方便进行事务操作
(6)降低 API 开发难度
IOC
IOC 容器
(1)IOC 底层原理
(2)IOC 接口(BeanFactory)
(3)IOC 操作 Bean 管理(基于 xml)
(4)IOC 操作 Bean 管理(基于注解)
什么是 IOC
(1)控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
(2)使用 IOC 目的:为了耦合度降低
原理
IOC 底层主要用到 3 个技术
xml 解析、工厂模式、反射
1 原始方式创建对象
原始方式通过 new 创建对象,耦合度太高
2 工厂模式创建对象
使用工厂模式解耦。
工厂模式不是最终方案,最终是IOC.
如下图,工厂本身存在耦合度(耦合度不可能消除),还可以进一步降低耦合度
3 IOC 创建对象
进一步降低耦合度:IOC。除了用到工厂模式,还得用 xml 解析 以及 反射.
以后要是有修改,改 xml 文件即可.
第一步:xml 配置要创建的对象.
第二步:创建工厂类,里面new对象
第三步:解析 xml 得到 class 属性值,然后通过反射 new 对象。如下图,newInstance() 这个方法就是实例化的.
BeanFactory 接口 & ApplicationContext 接口
BeanFactory 和 ApplicationContext
1、IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂 .
2、工厂需要实例化,Spring 提供 IOC 容器实现两种方式:(两个接口)
(1)BeanFactory
IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用 。
(2)ApplicationContext
BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用 。
3、 二者区别
BeanFactory:加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象 。(懒汉)
ApplicationContext:加载配置文件时候就会把在配置文件对象进行创建 。 (饿汉)
服务器启动时,这些对象都最好创建好,到时候直接用时效率就会更高了
ApplicationContext 接口有实现类
FileSystemXmlApplicationContext:得写配置文件在系统内的路径.
ClassPathXmlApplicationContext:src工程下的路径.
DI:依赖注入
就是注入属性.
普通 Bean 和 FactoryBean
1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)
2、普通 bean:在配置文件中定义 bean 类型就是返回类型
3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean ;
第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型;
public class MyBean implements FactoryBean<Course> { //声明泛型.
//定义返回 bean
@Override
public Course getObject() throws Exception { //返回类型在这里定义
Course course = new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {return null;}
@Override
public boolean isSingleton() {return false;}
}
Bean 的作用域:单例 or 多例
1、在 Spring 里面,设置创建 bean 实例是单实例还是多实例
单实例:同一个对象,地址不变.
多实例:每次都 new 新对象,地址改变.
2、在 Spring 里面,默认情况下,bean 是单实例对象
3、如何设置 单实例 还是 多实例
(1)在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
(2)scope 属性值 (有多个,常用的就是这两个)
第一个值 默认值,singleton,表示是单实例对象
第二个值 prototype,表示是多实例对象
(3)singleton 和 prototype 区别
第一:singleton 单实例,prototype 多实例
第二:设置 scope 值是 singleton 时候,加载 spring 配置文件时(饿汉)候就会创建单实例对象 .
设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用 getBean 方法时(懒汉)候创建多实例对象.
(感觉是因为多例,没法提前创建)
Spring 中 Bean 的作用域通常有下面几种
- singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的,对单例设计模式的应用。
- prototype : 每次请求都会创建一个新的 bean 实例。
- request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
- session : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
- global-session : 全局 session 作用域,仅仅在基于 portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。
Bean 的生命周期:Bean从创建至销毁的过程
1、生命周期是什么?
从对象创建到对象销毁的过程 。
2、bean 生命周期
(1)通过构造器创建 bean 实例 (利用无参数构造器,构造实例)
(2)为 bean 的属性设置值和对其他 bean 引用 (调用类的 set 方法)
(3)调用 bean 的初始化的方法 (需要进行配置初始化的方法,才能调用)
(4)bean 可以使用了 (对象已经获取到了)
(5)当容器关闭时候,调用 bean 的销毁的方法 (需要进行配置销毁的方法,类似初始化)
3、演示 bean 生命周期
public class Orders {
//无参数构造
public Orders() {
System.out.println("第一步 执行无参数构造创建 bean 实例");
}
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 调用 set 方法设置属性值");
}
//创建执行的初始化的方法
public void initMethod() {
System.out.println("第三步 执行初始化的方法");
}
//创建执行的销毁的方法
public void destroyMethod() {
System.out.println("第五步 执行销毁的方法");
}
}
<bean id="orders" class="com.atguigu.spring5.bean.Orders"
init-method="initMethod" destroy-method="destroyMethod"> <!--配置初始化/销毁方法-->
<property name="oname" value="手机"></property>
</bean>
@Test
public void testBean3() {
// ApplicationContext context =
// new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步 获取创建 bean 实例对象");
System.out.println(orders);
//手动让 bean 实例销毁
context.close();
}
4、完善 bean 声明周期,bean 的后置处理器,bean 生命周期有七步
相比于之前的 5 步,在初始化前后各增加一步!
实现接口 BeanPostProcessor,创建后置处理器.
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
(3)调用 bean 的初始化的方法(需要进行配置初始化的方法)
把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
(4)bean 可以使用了(对象获取到了)
(5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
XML自动装配(一般不用,一般都用注解)
1、什么是自动装配
根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入 .
2、演示自动装配过程
bean 标签属性 autowire,配置自动装配 .
autowire 属性常用两个值:
byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样 ;
byType 根据属性类型注入 ;
注解方式
1、什么是注解
(1)注解是代码特殊标记.
格式:@注解名称(属性名称=属性值, 属性名称=属性值..)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化 xml 配置
2、Spring 针对 Bean 管理中创建对象提供注解
下边四个注解功能是一样的,都可以用来创建 bean 实例。实际混用也不报错。
@Component :通用
@Service :可以标记 业务层
@Controller :可以标记 Web 层
@Repository :可以标记 Dao 层
3、基于注解方式实现属性注入
@Autowired
作用: 自动按照类型(byType)注入。
当使用注解注入属性时,set 方法可以省略。它只能注入其他 bean 类型。
当有多个类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就报错。
@Qualifier
作用: 在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。根据名称(byName)进行注入 。
它在给字段注入时不能独立使用,必须和 @Autowire 一起使用;但是给方法参数注入时,可以独立使用。
属性: value:指定 bean 的 id。
@Resource
作用: 直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。
属性: name:指定 bean 的 id。
@Value
作用: 注入基本数据类型和 String 类型数据的
属性: value:用于指定值
简单总结一下
- @Autowired 是 Spring 提供的注解,@Resource 是 JDK 提供的注解。
- @Autowired 默认的注入方式为 byType(根据类型进行匹配);
@Resource 默认的注入方式为 byName(根据名称进行匹配)。
- 当一个接口存在多个实现类的情况下,@Autowired 和 @Resource 都需要通过名称(指定 bean 的 Id)才能正确匹配到对应的 Bean。
Autowired 可以通过 @Qualifier 注解来显示指定名称;
@Resource可以通过 name 属性来显示指定名称。
AOP
什么是 AOP?
1、什么是 AOP
(1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得
业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
(3)使用登录例子说明 AOP
底层原理
1、AOP 底层使用动态代理
(1)有两种情况动态代理
第一种 有接口情况,使用 JDK 动态代理
创建接口实现类代理对象,增强类的方法
第二种 没有接口情况,使用 CGLIB 动态代理
创建子类的代理对象,增强类的方法
AOP(JDK 动态代理)
1、使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象(1)调用 newProxyInstance 方法
方法有三个参数:
第一参数,类加载器
第二参数,增强方法所在的类,这个类实现的接口,支持多个接口
第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分
2、编写 JDK 动态代理代码
(1)创建接口,定义方法
(2)创建接口实现类,实现方法
(3)使用 Proxy 类创建接口代理对象