Bean的作用域与生命周期
Bean的作用域
默认情况下,我们从Spring容器中拿到的对象均是单例的
singleton 作用域
注意: lazy-init是懒加载, 如果等于true时作用是指Spring容器启动的时候不会去实例化这个bean, 而
是在程序调用时才去实例化. 默认是false即Spring容器启动时实例化.
lazy-init属性(懒加载)
如果为false,则在IOC容器启动时会实例化bean对象,默认false
如果为true,则IOC容器启动时不会实例化Bean对象,在使用bean对象时才会实例化
lazy-init设置为false有什么好处?
1)可以提前发现潜在的配置问题
2)Bean 对象存在于缓存中,使用时不用再去实例化bean,加快程序运行效率
什么对象适合作为单例对象?
一般来说对于无状态或状态不可改变的对象适合使用单例模式。(不存在会改变对象状态的成员变量
比如:controller层、service层、dao层
prototype 作用域
Web应用中的作用域
1. request作用域
表示每个请求需要容器创建一个全新Bean
2. session作用域
表示每个会话需要容器创建一个全新Bean
3. globalSession作用域
类似于session作用域,其用于portlet(Portlet是基于Java的Web组件,由Portlet容器管理,并由容器处理请求,生产动态内容)环境的web应用。如果在非portlet环境将视为session作用域。
Bean的生命周期
在Spring中,Bean的生命周期包括Bean的定义、初始化、使用和销毁4个阶段
Bean的定义
Spring中,通常是通过配置文档的方式来定义Bean的,在一个配置文档中,可以定义多个Bean。
Bean 的初始化
默认在IOC容器加载时,实例化对象。
方式一:在配置文档中通过指定 init-method 属性来完成。
方式二: 实现 InitializingBean 接口。
Bean 的使用
方式一:使用 BeanFactory
方式二: 使用 ApplicationContext
Bean的销毁
可以在配置文件中指定bean对象的销毁所要执行的方发
destroymethod="destroy"></bea
通过 AbstractApplicationContext 对象,调用其close方法实现bean的销毁过程
代理模式
为某一个对象(委托类)提供一个代理(代理类),用来控制对这个对象的访问。委托类和代理类有一个共同的父类或父接口。代理类会对请求做预处理、过滤,将请求分配给指定对象。
代理模式的两个设计原则:
1. 代理类 与 委托类 具有相似的行为(共同)
2. 代理类增强委托类的行为
1. 静态代理
为某个对象提供一个代理,代理角色固定,以控制对这个对象的访问代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理
代理的三要素
a、有共同的行为(结婚) - 接口
b、目标角色(新人) - 实现行为
c、代理角色(婚庆公司) - 实现行为 增强目标对象行为
静态代理的特点
1、目标角色固定
2、在应用程序执行前就得到目标角色
3、代理对象会增强目标对象的行为
4、有可能存在多个代理 引起"类爆炸"(缺点)
静态代理的实现
1. 定义行为(共同) 定义接口
2. 目标对象(实现行为)
3.代理对象(实现行为、增强目标对象的行为)
.4. 通过代理对象实现目标对象的功能
2. 动态代理
动态代理比较灵活,可以根据需要通过反射机制在程序运行期间,动态的为目标对象创建代理.代理的行为可以代理多个方法,即满足生产需要的
同时又达到代码通用的目的。
动态代理的特点
1. 目标对象不固定
2. 在应用程序执行时动态创建目标对象
3. 代理对象会增强目标对象的行为
1. JDK 动态代理
JDK动态代理的目标对象必须有接口实现
2. CGLIB动态代理
cglib继承思想是针对类来实现代理的,它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
1. 添加依赖
在pom.xml文件中引入cglib的相关依赖
2. 定义类
实现MethodInterceptor接口
3. 调用方法
JDK代理与CGLIB代理的区别
JDK动态代理实现接口,Cglib动态代理继承思想
JDK动态代理(目标对象存在接口时)执行效率高于Ciglib
如果目标对象有接口实现,选择JDK代理,如果没有接口实现选择Cglib代理
日志处理带来的问题
我们有一个Pay(接口) 然后两个实现类,都需要重写pay()方法, 这时我们需要对pay方法进行性能监控,日志的添加等等怎么做?
对每个字符方法均做日志代码的编写处理
缺点: 代码重复太多, 添加的日志代码耦合度太高
使用装饰器模式 /代理模式改进解决方案
对于每个类做日志处理,并引用目标类,但是
如果待添加日志的业务类的数量很多,此时手动为每个业务类实现一个装饰器或创建对应的代理类,同时代码的耦合度也加大,需求一旦改变,改动的工程量也是巨大的。
Spring AOP
什么是Spring Aop?
面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
切面: 对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面
AOP能做什么?
主要应用于日志记录,性能统计,安全控制,事务处理等方面,实现公共功能性的重复使用。
AOP的特点
1. 降低模块与模块之间的耦合度,提高业务代码的聚合度。(高内聚低耦合)
2. 提高了代码的复用性。
3. 解耦提高系统的扩展性。(高版本兼容低版本)
4. 可以在不影响原有的功能基础上添加新的功能
AOP的底层实现
动态代理(JDK + CGLIB)
AOP基本概念
1. Joinpoint(连接点)
被拦截到的每个点,spring中指被拦截到的每一个方法,spring aop一个连接点即代表一个方法的执行。
2. Pointcut(切入点)
对连接点进行拦截的定义(匹配规则定义 规定拦截哪些方法,对哪些方法进行处理),spring 有专门的表达式语言定义。
3. Advice(通知)
拦截到每一个连接点即(每一个方法)后所要做的操作
1. 前置通知 (前置增强)— before() 执行方法前通知
2. 返回通知(返回增强)— afterReturn 方法正常结束返回后的通知
3. 异常抛出通知(异常抛出增强)— afetrThrow()
4. 最终通知 — after 无论方法是否发生异常,均会执行该通知。
5. 环绕通知 — around 包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行
4. Aspect(切面)
切入点与通知的结合,决定了切面的定义,切入点定义了要拦截哪些类的哪些方法,通知则定义了拦截过方法后要做什么,切面则是横切关注点的抽象,与类相似,类是对物体特征的抽象,切面则是横切
关注点抽象。
5. Target(目标对象)
代理的目标对象
6.代理的目标对象
将切面应用到目标对象并生成代理对象的这个过程即为织入
.7. Introduction(引入)
在不修改原有应用程序代码的情况下,在程序运行期为类动态添加方法或者字段的过程称为引入