Spring涉及到的设计模式
- 简单工厂模式
- 一个工厂类根据传入的参数,动态决定创建哪一个类
public abstract class AbstractBeanFactory extends ***{
//根据传入的名字 创建某个类
@Override
public Object getBean(String name,……) throws BeansException {
// doGetBean才是真正向IoC容器获取被管理Bean的过程
return doGetBean(name, null, null, false);
}
}
}
- 工厂模式
- 将对象的创建及初始化交给工厂对象
public abstract class AbstractAutowireCapableBeanFactory(){
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 1.利用工厂模式进行实例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
根据不同的条件进行实例化
}
- 单例模式
- 创建单例模式的对象
- 适配器
- aop中生成代理对象前,设置拦截器,通过拦截器中的内容增强了代理方法的功能。
Adapter类接口:Target
public interface AdvisorAdapter {
boolean supportsAdvice(Advice advice);
MethodInterceptor getInterceptor(Advisor advisor);
}
MethodBeforeAdviceAdapter类,Adapter
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
- 包装器 Decortor
- 我们的项目需要访问不同的数据库。如何动态的切换不同的数据源呢
一种是
applicationContext中配置所有的dataSource 可能是不同类型的,比如不同的数据库
二是 org.springframework.jndi.JndiObjectFactoryBean
sessionFactory根据用户的每次请求,将dataSource设成不同的数据源
spring用到的包装器模式在类名上有两种表现,一种含有 Wrapper 另一种 Decorator
基本上都是动态的给一个对象添加些额外的职责
- 代理模式
- 从结构上看和Decorator模式类似,但是proxy是控制,更像是对功能的限制,而Decorator是增加职责
- 比如JdkDynamicAopProxy和Cglib2AopProxy。
- 观察者
- 定义对象间的一对多的依赖关系,当一个对象状态发生变化时,所有依赖他的对象都会被通知并更新
spring中Observer模式常用的地方是listener的实现。如ApplicationListener。
- 策略
- 定义一系列算法,封装起来,并且使他们可相互替换。
- 实例化对象的时候 用到了
- AOP 选择不同的代理模式
分析角色
- 抽象策略角色--AopProxy
- 具体策略角色--Cglib2AopProxy和JdkDynamicAopProxy
-
环境角色--ProxyCreatorSupport
调用方式:ProxyFactoryBean.java
抽象策略
public interface AopProxy {
Object getProxy();
Object getProxy(@Nullable ClassLoader var1);
}
class CglibAopProxy implements AopProxy, Serializable {
public Object getProxy() {
//实现
}
}
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler(){
public Object getProxy() {
//实现
}
}
public class DefaultAopProxyFactory implements AopProxyFactory(){
public AopProxy createAopProxy(AdvisedSupport config) {
//根据这个class是不是接口来选择 不同的代理方式
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass)?new ObjenesisCglibAopProxy(config):new JdkDynamicAopProxy(config));
}
}
public class ProxyCreatorSupport extends AdvisedSupport(){
//这里应该用到了观察者模式
private List<AdvisedSupportListener> listeners = new LinkedList();
public void addListener(AdvisedSupportListener listener) {
Assert.notNull(listener, "AdvisedSupportListener must not be null");
this.listeners.add(listener);
}
}
策略2
根据不同的类型 用不同的算法实例化
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory{
@Override
public Object getBean(String name,……) throws BeansException {
// doGetBean才是真正向IoC容器获取被管理Bean的过程
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(){
//先从缓存中取,对于单例模式的对象只创建一次
Object sharedInstance = getSingleton(beanName);
//缓存有
if (sharedInstance != null && args == null) {
//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
//BeanFactory是管理容器中Bean的工厂,而FactoryBean是创建创建对象的工厂Bean,两者之间有区别
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else{
//缓冲中没有,则继续判断其模式
// Create bean instance.
if (mbd.isSingleton()) {
//sharedInstance 单例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}else if (mbd.isPrototype()) {
//prototypeInstance 代理
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}else {
//根据Bean定义资源中配置的生命周期范围,选择实例化Bean的合适方法
String scopeName = mbd.getScope();
//scopedInstance
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
}
}
}
- 模板方法
定义一个操作中算法的框架,实现延伸到子类
spring中的jdbcTemplate中excute
Template Method模式一般是需要继承的。这里想要探讨另一种对Template Method的理解。spring中的JdbcTemplate,在用这个类时并不想去继承这个类,因为这个类的方法太多,但是我们还是想用到JdbcTemplate已有的稳定的、公用的数据库连接,那么我们怎么办呢?我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码,而且这段代码会用到JdbcTemplate中的变量。怎么办?那我们就用回调对象吧。在这个回调对象中定义一个操纵JdbcTemplate中变量的方法,我们去实现这个方法,就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate,从而完成了调用。这可能是Template Method不需要继承的另一种实现方式吧。