委派模式与模板模式(2)

三、委派模式在源码中的体现


JDK 中有一个典型的委派 ,众所周知 JVM 在加载类是用的双亲委派模型 ,这又是什么呢?—类加载器在加载类时 , 先把这个请求委派给自己的父类加载器去执行 ,如果父类加载器还存在父类加载器 ,就继续向上委派,直到顶层的启动类加载器。如果父类加载器能够完成类加载,就成功返回,如果父类加载器无法完成加载,那么子加载器才会尝试自己去加载。从定义中可以看到双亲加载模型一个类加载

器加载类时 , 首先不是自己加载 ,而是委派给父加载器。下面我们来看看 loadClass()方法的源码 ,此方法在 Classloader 中。在这个类里就定义了一个双亲,用于下面的类加载。


public abstract class ClassLoader {
    private final ClassLoader parent;
    
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
}


常用代理执行方法 invoke

同样在反射里的 Method 类里我们常用代理执行方法 invoke也存在类似的机制。


public final class Method extends Executable {
    @CallerSensitive
    public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }
        return ma.invoke(obj, args);
    }
}


看完代码 , 相信小伙伴们对委派和代理区别搞清楚了吧。


Spring loC中 在调用 doRegisterBeanDefinitions()


下面来看一下委派模式在Spring 中的应用在Spring loC中 在调用 doRegisterBeanDefinitions()


方法时即 BeanDefinition进行注册的过程中,会设置 BeanDefinitionParserDelegate类型的 Delegate对象传给 this.delegate 并将这个对象作为一个参数传给 :parseBeanDefinitions(root, this.delegate)


中 ,然后主要的解析的工作就是通过 delegate作为主要角色来完成的, 可以看到下方代码 :


public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    // 判断节点是否属于同一令名空间 , 是则执行后续的解析 
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        //注解定义的 context 的 namespace 进入到这个分支中
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }
}   


其中最终能够走到 bean 注册部分的是 ,会进入到 parseDefault Element(ele, delegate)中,然后


针对不同的节点类型针对 bean 的节点进行真正的主册操作而在这个过程中,delegate 会对element


进行 parseBeanDefinitionElement , 得到了一个 BeanDefinitionHolder 类型的对象,之后通过这个


对象完成真正的注册到 Factory 的操作。


SpringMVC 的 DispatcherServlet

下面我们再来还原一下 SpringMVC 的 DispatcherServlet 是如何实现委派模式的。创建业务类


MemberController :


public class MemberController {
    public void getMemberById(String mid) {
    }
}


上一篇:委派模式与模板模式(5)


下一篇:委派模式与模板模式(1)