前言
新的一年的学习,学习一项新知识,最好的方法就是有优秀的案例配合学习,不仅能够帮助你学习新知识,而且还可以让你了解到它能运用到什么情况下的场景。建议大家学习新知识的时候,不要仅限于理论,配合优秀的案例场景可以事半功倍。
这次想带大家了解的是抽象工厂模式(Abstract Factory)的实现,要说案例,那肯定还是Spring的案例是最适合的。新手学习基础,进阶学习源码,适用于任何一个阶段的开发者。
基本概念
抽象工厂提供了一种方式,让具有同一主题的单独的工厂给封装起来。在我们正常使用中,客户端程序需要创建抽象方法的具体实现,然后使用抽象工厂作为接口来创建具体的对象。而客户端也不需要关心其中的具体实现,因为调用的是统一且通用的接口。
举例一下Spring AOP的具体实现
- interface接口 — org.springframework.aop.framework.AopProxyFactory
- class唯一实现 — org.springframework.aop.framework.DefaultAopProxyFactory
package org.springframework.aop.framework; public interface AopProxyFactory { /** * 为给定的AOP配置创建AopProxy。 */ AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException; }
这是一个interface接口,它有一个返回类型为AopProxy,method名称为createAopProxy的方法,但凡是实现了AopProxyFactory这个接口的,都需要实现createAopProxy方法。
AopProxyFactory这个接口的作用就是创建一个CGLIB代理或JDK动态代理,因此它的返回类型是比较罕见的interface类型。
public interface AopProxy { Object getProxy(); Object getProxy(@Nullable ClassLoader classLoader); }
实际用法上,到时候只需要调用getProxy方法就行,不需要理会返回的这个AopProxy对象是一个CGLIB代理对象,还是一个JDK动态代理对象。
在这个上面,无论是JdkDynamicAopProxy动态代理,还是ObjenesisCglibAopProxy代理,他们都 implements 了AopProxy这个接口类,也是一种抽象工厂模式。因此无论是返回JdkDynamicAopProxy对象,还是返回ObjenesisCglibAopProxy对象,都可以使用AopProxy这个接口类作为统一的返回类型。
这就是一种抽象,而在SpringAOP中,需要创建一个CGLIB代理或JDK动态代理,所有DefaultAopProxyFactory这一个类继承且实现了它。以下是DefaultAopProxyFactory的实现类源码:
package org.springframework.aop.framework; import java.io.Serializable; import java.lang.reflect.Proxy; import org.springframework.aop.SpringProxy; /** * * 对于给定的AdvisedSupport实例,如果下列情况之一为真,则创建CGLIB代理: * 1.优化标志被设置 * 2.设置proxyTargetClass标志 * 3.未指定代理接口 * 通常,指定proxyTargetClass来强制使用CGLIB代理,或者指定一个或多个接口来使用JDK动态代理。 */ @SuppressWarnings("serial") public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { //TargetSource不能确定目标类:创建代理需要接口或目标。 throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } /** * 确定所提供的AdvisedSupport是否只指定了SpringProxy接口(或者根本没有指定代理接口)。 */ private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) { Class<?>[] ifcs = config.getProxiedInterfaces(); return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]))); } }
SpringAOP中默认的AopProxyFactory实现,用于创建一个CGLIB代理或JDK动态代理。
根据源码可知,创建CGLIB代理,只需要满足任意一种条件即可
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))
- 1.优化标志被设置
- 2.设置proxyTargetClass标志
- 3.未指定代理接口
若三个条件都不满足,则创建Jdk动态代理。
但是在每个不同的业务中,不一定就需要跟AopProxyFactory一样,返回类型是一个interface,你可以是一个String,也可以是一个Object、Boolean都可以。
但是在命名规范上是非常有讲究的
- 类命名需要以Factory结尾
- 类命名前面的名词,一般是被创建的对象,比如AopProxyFactory,那么抽象的方法返回类型就是AopProxy
- 方法命名,一般都是createXxx、newXxx、getXxx、buildXxx
结束
抽象工厂模式的学习就告一段落了,感兴趣的同学可以打开idea,更深层次的去了解AopProxyFactory的源码,以及他们模式的使用。