设计伊始
Spring 是为解决企业级应用开发的复杂性而设计,她可以做很多事。但归根到底支撑Spring的仅仅是少许的基本理念,而所有地这些的基本理念都能可以追溯到一个最根本的使命:简化开发。这是一个郑重的承诺,其实许多框架都声称在某些方面做了简化。
而Spring则立志于全方面的简化Java开发。对此,她主要采取了4个关键策略:
1,基于POJO的轻量级和最小侵入性编程;
2,通过依赖注入和面向接口松耦合;
3,基于切面和惯性进行声明式编程;
4,通过切面和模板减少样板式代码;
而他主要是通过:面向Bean、依赖注入以及面向切面这三种方式来达成的。
而设计如此精妙的spring,其中肯定是有许多设计模式的,下面我们就通过阅读分析spring的源码来感受spring的密码。
贴一个spring源码下载地址,下载托管在github了。
https://github.com/spring-projects/spring-framework/tags
我下的是spring3.2.5 release
常见的九种设计模式
分别是:简单工厂、工厂方法、单例模式、适配器模式、包装器模式、代理模式、观察者模式、策略模式、模板方法模式
1.工厂模式
org.springframework.beans.factory 这里是定义spring IOC容器接口的包,在这个包里有我们熟悉的BeanFactory
package org.springframework.beans.factory;
public interface BeanFactory {
/**
*这里是对FactoryBean的转义定义,如果使用bean的名字检索FactoryBean,得到的是工厂生成的对象,
*如果需要得到工厂本身,需要转义。For example, if the bean named
* <code>myJndiObject</code> is a FactoryBean, getting <code>&myJndiObject</code>
* will return the factory
*/
String FACTORY_BEAN_PREFIX = "&";
/**
*这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。
*/
Object getBean(String name) throws BeansException;
/**
*这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果
*根据名字取得的bean实例的Class类型和需要的不同的话。
*/
Object getBean(String name, Class requiredType) throws BeansException;
/**
*这里提供对bean的检索,看看是否在IOC容器有这个名字的bean
*/
boolean containsBean(String name);
/**
*这里根据bean名字得到bean实例,并同时判断这个bean是不是单例
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
*这里得到bean实例的Class类型
*/
Class getType(String name) throws NoSuchBeanDefinitionException;
/**
*这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
*/
String[] getAliases(String name);
}
- spring中BeanFactory和ApplicationContext的创建中都用到了典型的静态工厂模式。Bean 的创建采用了的工厂模式,他的顶级接口是 BeanFactory。BeanFactory 有三个子接口:ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactor。这三个接口主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。这三个子接口集成了顶级接口并对BeanFactory的功能进行了增强,称为二级接口;ConfigurableBeanFactory对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry,可以被称为三级接口;ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,称为四级接口。其余的为抽象类,实现了Spring Bean四级接口所定义的所有功能。
一般来说采用BeanFactory的子接口ApplicationContext来创建BeanFactory的实例。ApplicationContext通常使用如下两个实现类:
FileSystemXmlApplicationContext:以基于文件系统的XML配置文件创建ApplicationContext实例。
ClassPathXmlApplicationContext:以类加载路径下的XML配置文件创建的ApplicationContext实例
public void testAC() {
//1.在这里ApplicationContext接口继承了ListableBeanFactory, HierarchicalBeanFactory等二级接口
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/xyf/a_hello/applicationContext.xml");
//2.从容器获取Bean
User user = (User) ac.getBean("user");
System.out.println(user);
}
在spring中,BeanFactory拥有类似的功能,它负责实例化、配置和管理对象。我们一般用的BeanFactory的实现类ApplicationContext,这个类会自动解析我们配置的applicationContext.xml,然后调用实现后的getBean方法然后根据我们配置的bean来new对象,将new好的对象放进一个容器中,键就是我们bean的id,值就是new的对象。
在这里给出简单工厂模式的实现
//简单工厂模式
package cn.xyf.factory;
/**
* @author Dale
* 封装一个雷峰类
*/
public class LeiFeng {
//扫地
public void sweep(){
System.out.println("扫地");
}
//洗衣
public void wash(){
System.out.println("洗衣");
}
//买米
public void buyRice(){
System.out.println("买米");
}
}
//大学生子类
class UnderGraduate extends LeiFeng{
}
//社区志愿者子类
class Volunteer extends LeiFeng{
}
package cn.xyf.factory;
/**
* @author Dale
* 简单工厂模式
*/
public class SimpleFactory {
//静态方法创建雷锋对象
public static LeiFeng createLeiFeng(String type){
LeiFeng result = null;
switch(type){
case "UnderGraduate":
result = new UnderGraduate();
break;
case "UnderGrate":
result = new Volunteer();
break;
}
return result;
}
}
package cn.xyf.factory;
/**
* @author Dale
* java 工厂模式
*/
public class Client {
public static void main(String[] args) {
//1.简单工厂模式
LeiFeng s1 = SimpleFactory.createLeiFeng("UnderGraduate");
LeiFeng s2 = SimpleFactory.createLeiFeng("UnderGrate");
s1.wash();
s2.buyRice();
}
在这里补充一下简单工厂、工厂、抽象工厂三者的区别
简单工厂
简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。
不修改代码的话,是无法扩展的。工厂方法
工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。
在同一等级结构中,支持增加任意产品。抽象工厂
抽象工厂是应对产品族概念的。比如说,每个汽车公司可能要同时生产轿车,货车,客车,那么每一个工厂都要有创建轿车,货车和客车的方法。
应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品。
小结
★工厂模式中,重要的是工厂类,而不是产品类。产品类可以是多种形式,多层继承或者是单个类都是可以的。但要明确的,工厂模式的接口只会返回一种类型的实例,这是在设计产品类的时候需要注意的,最好是有父类或者共同实现的接口。
★使用工厂模式,返回的实例一定是工厂创建的,而不是从其他对象中获取的。
★工厂模式返回的实例可以不是新创建的,返回由工厂创建好的实例也是可以的。
区别
简单工厂 : 用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
以上三种工厂 方法在等级结构和产品族这两个方向上的支持程度不同。所以要根据情况考虑应该使用哪种方法。