Spirng中的设计模式

1.解释器模式【interpreter】

Spring在SpEL中应用的解释器模式,很典型的应用场景。
Spring的SpEL是一门DSL语言,它的表达式由org.springframework.expression.ExpressionParser的实现负责分析和执行。ExpressionParser变得实现接收SpEL表达式最为输入字符串,并将其转换为一个org.springframework.expression.Expression实例。

2.构建者模式【Builder】

Spring中典型的构建者类是BeanDefinitionBuilder,主要是在加载自定义的BeanDfinition时使用。
Spring仅认为"http://www.springframework.org/schema/beans"命名空间属于默认命名空间,其他都属于自定义的命名空间,在解析自定义的命名空间时,需要找出该命名空间对应的BeanDefinitionParser,而BeanDefinitionBuilder即使在解析这些自定义的元素时候使用的。

举例子,在解析context:时候,其对应的BeanDefinitionParser是PropertyPlaceholderBeanDefinitionParser:

public abstract class AbstractBeanDefinitionParser implements BeanDefinitionParser {
	public final BeanDefinition parse(Element element, ParserContext parserContext) {
		// 为了将真实的解析逻辑,下沉到子类,调用parserInternal来解析dom元素
		AbstractBeanDefinition definition = parseInternal(element, parserContext);
		if (definition != null && !parserContext.isNested()) {
			try {
				String id = resolveId(element, definition, parserContext);
				if (!StringUtils.hasText(id)) {
					parserContext.getReaderContext().error(
							"Id is required for element '" + parserContext.getDelegate().getLocalName(element)
									+ "' when used as a top-level tag", element);
				}
				String[] aliases = null;
				if (shouldParseNameAsAliases()) {
					String name = element.getAttribute(NAME_ATTRIBUTE);
					if (StringUtils.hasLength(name)) {
						aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
					}
				}
				BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
				registerBeanDefinition(holder, parserContext.getRegistry());
				if (shouldFireEvents()) {
					BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
					postProcessComponentDefinition(componentDefinition);
					parserContext.registerComponent(componentDefinition);
				}
			}
			catch (BeanDefinitionStoreException ex) {
				String msg = ex.getMessage();
				parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element);
				return null;
			}
		}
		return definition;
	}
}
public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDefinitionParser {
	protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
		// 构建一个BeanDefinitionBuilder
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
		String parentName = getParentName(element);
		if (parentName != null) {
			// 向构建者设置parent属性
			builder.getRawBeanDefinition().setParentName(parentName);
		}
		Class<?> beanClass = getBeanClass(element);
		if (beanClass != null) {
			builder.getRawBeanDefinition().setBeanClass(beanClass);
		}
		else {
			String beanClassName = getBeanClassName(element);
			if (beanClassName != null) {
				builder.getRawBeanDefinition().setBeanClassName(beanClassName);
			}
		}
		builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
		BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
		if (containingBd != null) {
			// 设置Scope,同时保证内外作用域必须一致
			builder.setScope(containingBd.getScope());
		}
		if (parserContext.isDefaultLazyInit()) {
			// 设置延迟初始化
			builder.setLazyInit(true);
		}
		doParse(element, parserContext, builder);
		// 从BeanDefinitionBuilder提取出构建的对象,即BeanDefinition
		return builder.getBeanDefinition();
	}
}

构建者的实现很简单,Spring的实现亦如此,读者自行阅读BeanDefinitionBuilder即可。

3.工厂方法

Spring通过配置的形式,支持静态工厂方法【static factory method】和实例工厂方法【instance factory method】

静态工厂方法【static factory method】
    <bean id="staticFactoryMethod" class="com.telecom.spring.designpattern.StaticFactoryMethod" factory-method="instance" >
    </bean>

POJO:

public class StaticFactoryMethod {

    /**
     * 静态工厂方法,注意,该方法一定要是静态的
     * @return
     */
    public static StaticFactoryMethod instance(){
        return new StaticFactoryMethod();
    }
}

在< bean>中指定class,即静态工厂类,然后在facory-method中指定工厂方法

实例工厂方法[instance factory method]
    <bean id="instanceFactoryMethod" class="com.telecom.spring.designpattern.InstanceFactoryMethod">
        
    </bean>
    
    <bean id="targetBean" factory-bean="instanceFactoryMethod" factory-method="createTargetBean">
        
    </bean>

POJO:

public class InstanceFactoryMethod {
    /**
     * 实例工厂方法
     * @return
     */
    public TargetBean createTargetBean(){
        return new TargetBean();
    }
}

与通过静态工厂方法实例化类似,使用实例工厂方法实例化将从容器中调用现有bean的非静态方法来创建新bean。要使用此机制,请保留class属性为空,并在factory-bean属性中,指定当前(或父或父)容器中的bean的名称,该容器包含要调用来创建对象的实例方法。使用factory-method属性设置factory方法的名称。

4.抽象工厂

5.代理模式【proxy】

代理的工作原理类似于对象的镜像。由于它,代理对象不仅可以覆盖真实对象,还可以扩展它们的特性。代理是一个封装了真实对象的对象。

Spring中代理模式的实现栗子是:org.springframework.aop.framework.ProxyFactoryBean。这个工厂基于Spring bean构建AOP代理。ProxyFactoryBean类实现了FactoryBean接口,它定义了getObject()方法。此方法用于将所需bean的实例返回到bean工厂。getObject()方法返回的不是Bean实例的原型,而是AOP代理后的Bean实例。

    <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>
    <!--代理模式-->
    <bean id="proxyBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target">
            <bean class="com.telecom.spring.designpattern.TargetBean">
                <property name="sugar" value="Piemon"/>
            </bean>
        </property>
        <property name="interceptorNames">
            <list>
                <value>debugInterceptor</value>
            </list>
        </property>
    </bean>
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config/Bootstrap_test.xml");

        TargetBean proxy = (TargetBean) context.getBean("proxyBean");

        System.out.println(proxy.getSugar());
    }

Spring的ProxyFacroyBean与将Spring Ioc与Spring Aop结合了起来。但是除此之外,Spring还支持Spring Ioc无关的Bean的代理,提供该特性支持的是ProxyFactory。我们可以以编码的形式,完成对某个对象的代理,就像使用JDK动态代理一样。

    public static void main(String[] args) {

        ProxyFactory proxyFactory = new ProxyFactory();

        proxyFactory.setTarget(new TargetBean("A"));

        proxyFactory.addAdvice(new BeforeConstructAdvice());

        TargetBean targetBean = (TargetBean) proxyFactory.getProxy();

        System.out.println(targetBean.getSugar());
    }

    public static class BeforeConstructAdvice implements MethodBeforeAdvice {

        @Override
        public void before(Method method, Object[] arguments, Object target) throws Throwable {
            System.out.println("action before ...");
        }

    }

5.策略模式【Strategy】

Spring支持对各种资源的加载,ResourceLoader负责将给定的路径地址,解析为Resource资源。
Resource是对资源的高度抽象,因此他就是策略模式中的Strategy接口。
Resource的子类则对应于具体的策略:

  • ByteArrayResource:二进制数组表示的资源,二进制数组资源可以在内存中通过程序构造
  • ClassPathResource:类路径下的资源,资源以相对于类路径的方式表示。
  • FileSystemResource:文件系统资源,资源以文件系统路径的方式表示,如 C:\Users\admin\Desktop\xx.txt
  • InputStreamResource:对应一个InputStream的资源。
  • ServletContextResource:为访问Web容器上下文中的资源而设计的类,负责以相对于Web应用根目录的路径加载资源,它支持以流和URL的方式访问,在WAR解包的情况下,也可以通过File的方式访问,该类还可以直接从JAR包中访问资源。
  • UrlResource:封装了java.net.URL,它使用户能够访问任何可以通过URL表示的资源,如文件系统的资源、HTTP资源、FTP资源等。
    而负责选取策略的Context,则是ApplicationContext,或者说是PathMatchingResourcePatternResolver,它是ResourceLoader的实现,ApplicationContext虽然继承了DefaultResourceLoader类,但是他还是将解析的工作,委托给了PathMatchingResourcePatternResolver,因为他的功能更全面~

6.模板模式【Template】

太多地方使用了,定义骨干,将逻辑下沉。

7.观察者模式【Observer】

Spring的ApplicationEventPublisher、ApplicationEventMulticaster

8.适配器【Adapter】

9.装饰模式【Decorator】

10.单例模式【Singleton】

11.访问者模式【Visitor】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值