Spring系列--springIOC⽤到的设计模式
⽂章⽬录
前⾔
Spring作为⼀款及其优秀的框架,其代码的编写⾮常优秀,⾥⾯采⽤了⼤量的设计模式。
叙述
Spring IOC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。IOC 容器负责创建对象,将对象连接在⼀起,配置这些对象,并从创建中处理这些对象的整个⽣命周期,直到它们被完全销毁。
⼯⼚模式
Spring使⽤⼯⼚模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。
两者对⽐:
BeanFactory :延迟注⼊(使⽤到某个 bean 的时候才会注⼊),相⽐于ApplicationContext 来说会占⽤更
少的内存,程序启动速度更快。
ApplicationContext :容器启动的时候,不管你⽤没⽤到,⼀次性创建所有 bean 。BeanFactory 仅提供了最基本的依赖注⼊⽀持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能还有额外更多功能,所以⼀般开发⼈员使⽤ApplicationContext会更多。
Spring 实现单例的⽅式:
ApplicationContext的三个实现类:
ClassPathXmlApplication:把上下⽂⽂件当成类路径资源。
FileSystemXmlApplication:从⽂件系统中的 XML ⽂件载⼊上下⽂定义信息。
XmlWebApplicationContext:从Web系统中的XML⽂件载⼊上下⽂定义信息。
import t.ApplicationContext;
import t.support.FileSystemXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(
"C:/work/IOC Containers/springframework.applicationcontext/src/main/l");
HelloApplicationContext obj = (HelloApplicationContext) Bean("helloApplicationContext");
}
}
单例模式
Spring 中 bean 的默认作⽤域就是 singleton(单例)的。
Spring 实现单例的⽅式:
xml : <bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>
注解:@Scope(value = "singleton")
Spring 通过 ConcurrentHashMap 实现单例注册表的特殊⽅式实现单例模式。Spring 实现单例的核⼼代码如下
// 通过 ConcurrentHashMap(线程安全)实现单例注册表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 检查缓存中是否存在实例
Object singletonObject = (beanName);
if (singletonObject == null) {
//...省略了很多代码
try {
singletonObject = Object();
}
//...省略了很多代码
// 如果实例对象在不存在,我们注册到单例注册表中。
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
//将对象添加到单例注册表
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
}
}
}
策略模式
在策略模式(Strategy Pattern)中,⼀个类的⾏为或其算法可以在运⾏时更改。这种类型的设计模式属于⾏为型模式。在策略模式中,我们创建表⽰各种策略的对象和⼀个⾏为随着策略对象改变⽽改变的 context 对象。策略对象改变 context 对象的执⾏算法。策略模式实际就是⼀堆算法族的封装。
Spring中策略模式的应⽤
当bean需要访问资源配置⽂件时,Spring有两种⽅式
代码中获取Rescource实例
依赖注⼊
第⼀种⽅式需要获取rescource资源的位置,代码中耦合性太⾼,⽽今我们⼀直使⽤注解,依赖注⼊的⽅式去获取。这样的话就⽆需修改程序,只改配置⽂件即可。
<beans>
spring ioc注解<bean id="test" class="ample.Test">
<!-- 注⼊资源 -->
<property name="tmp" value="l"/>
</bean>
</beans>
在依赖注⼊的过程中,Spring会调⽤ApplicationContext 来获取Resource的实例。然⽽,Resource 接⼝封装了各种可能的资源类型,包括了:UrlResource,ClassPathResource,FileSystemResource等,
Spring需要针对不同的资源采取不同的访问策略。在这⾥,Spring让ApplicationContext成为了资源访问策略的“决策者”。在资源访问策略的选择上,Spring采⽤了策略模式。当 Spring 应⽤需要进⾏资源访问时,它并不需要直接使⽤ Resource 实现类,⽽是调⽤ ApplicationContext 实例的getResource() ⽅法来获得资源,ApplicationContext 将会负责选择 Resource 的实现类,也就是确定具体的资源访问策略,从⽽将应⽤程序和具体的资源访问策略分离开来。
ApplicationContext ctx = new Class PathXmlApplicationContext("l");
Resource res = Resource("l");
上⾯的代码中,Spring 将采⽤和 ApplicationContext 相同的策略来访问资源。即: ApplicationContext 是ClassPathXmlApplicationContext,则res 就是 ClassPathResource 实例。若将代码改为:
ApplicationContext ctx = new Class FileSystemXmlApplicationContext("l");
则再次调⽤Resource时,res 就是 ClassPathResource 实例。
装饰者模式
通过使⽤修饰模式,可以在运⾏时扩充⼀个类的功能。原理是:增加⼀个修饰类包裹原来的类,包裹的⽅式⼀般是通过在将原来的对象作为修饰类的构造函数的参数。装饰类实现新的功能,但是,在不需要⽤到新功能的地⽅,它可以直接调⽤原来的类中的⽅法。修饰类必须和原来的类有相同的接⼝。
Spring中装饰器模式的使⽤
Spring中类中带有Wrapper的都是包装类,如下创建bean就是典型的装饰器模式
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = ve(beanName);
}
if (instanceWrapper == null) {
//根据指定的bean使⽤对应的侧脸创建新的实例,如⼯⼚⽅法,构造函数⾃动注⼊,简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? WrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? WrappedClass() : null);
if (beanType != null) {
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new ResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
}
感谢您的阅读~~
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论