天天看点

Tomcat8.x 上下文(StandardContext)中(名称上下文(NamingContext)的创建->名称上下文(NamingContext))的使用

名称上下文(用于存放资源、被实例管理用来查找资源是否存在于名称上下文中)

// 名称上下文(用于全局资源、被实例管理用来查找资源是否存在于名称上下文中)
		// 名称上下文的创建---------1
		class org.apache.catalina.core.StandardContext{
			protected synchronized void startInternal() throws LifecycleException {
//		        org.apache.catalina.startup.ContextConfig
		        setConfigured(false); // 触发配置事件
		        
		        if (getNamingContextListener() == null) {
	            	// 创建名称上下文监听器
	                NamingContextListener ncl = new NamingContextListener();
	                ncl.setName(getNamingContextName());
	                ncl.setExceptionOnFailedWrite(getJndiExceptionOnFailedWrite());
	                // 把名称上下文监听器注入 org.apache.catalina.core.StandardContext
	                addLifecycleListener(ncl);
	                
	                setNamingContextListener(ncl); // 设置"名称上下文"监听器!!!
	            }
		        
		        // 在org.apache.catalina.core.NamingContextListener事件处理器中,内部调用了createNamingContext()创建 envCtx
		        fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
		        
		        // 实例管理器
		        if (getInstanceManager() == null) { // 如果实例管理器为空,实例管理器用来管理实例,如:org.apache.jasper.servlet.JspServlet,cn.java.MyServlet
                    javax.naming.Context context = null;
                    if (isUseNaming() && getNamingContextListener() != null) {
                    	// 在org.apache.catalina.core.NamingContextListener事件处理器中,内部调用了createNamingContext()创建 envCtx
                    	// org.apache.catalina.core.NamingContextListener.getEnvContext();
                    	// context === org.apache.naming.NamingContext ... 
                        context = getNamingContextListener().getEnvContext();
                    }
                    Map<String, Map<String, String>> injectionMap = buildInjectionMap(
                            getIgnoreAnnotations() ? new NamingResourcesImpl(): getNamingResources());
                   
                    // 设置实例管理器 org.apache.catalina.core.DefaultInstanceManager
                    // !!! context === org.apache.naming.NamingContext
                    setInstanceManager(new DefaultInstanceManager(context,
                            injectionMap, this, this.getClass().getClassLoader()));
                }
			}
		}

		// 名称上下文监听器
		class org.apache.catalina.core.NamingContextListener{
			
			 // 事件处理器,创建名称上下文
			 public void lifecycleEvent(LifecycleEvent event) {
			        container = event.getLifecycle();
			        if (Lifecycle.CONFIGURE_START_EVENT.equals(event.getType())) {
		                Hashtable<String, Object> contextEnv = new Hashtable<>();
		                namingContext = new NamingContext(contextEnv, getName()); // 创建名称上下文----------
		                ContextAccessController.setSecurityToken(getName(), token);
		                ContextAccessController.setSecurityToken(container, token);
		                ContextBindings.bindContext(container, namingContext, token);
	                    createNamingContext(); // 创建“名称上下文”
			        }
			 }
			 
			 // 创建名称上下文
			 private void createNamingContext()
				        throws NamingException {
			    	// container === org.apache.catalina.core.StandardServer
			        if (container instanceof Server) { // 走这里
			            compCtx = namingContext; // org.apache.naming.NamingContext
			            envCtx = namingContext;
			        } else {
			            compCtx = namingContext.createSubcontext("comp");
			            envCtx = compCtx.createSubcontext("env");
			        }
			        // Resources
			        ContextResource[] resources = namingResources.findResources();
			        for (i = 0; i < resources.length; i++) {
			            addResource(resources[i]);
			        }
			 }
		}
		
		
		//名称上下文的使用 ------------------2
		class org.apache.catalina.core.StandardWrapperValve{
			public final void invoke(Request request, Response response)
			        throws IOException, ServletException {
				//!!!!!!!!!
            	// !!!!! 加载Servlet类,创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
                // !!!!! 调用Servlet对象的init方法
                servlet = wrapper.allocate();
			}
		}
		
		// Servlet的包装器
		class org.apache.catalina.core.StandardWrapper{
			public Servlet allocate() throws ServletException {
				// !!!!! 加载Servlet类,创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
                // !!!!! 调用Servlet对象的init方法
                instance = loadServlet();
			}
			
			public synchronized Servlet loadServlet() throws ServletException {
				 //!!!实例管理器 org.apache.catalina.core.StandardContext
	            // instanceManager === org.apache.catalina.core.DefaultInstanceManager
	            InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
            	// 创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
            	// 如:servletClass === org.apache.jasper.servlet.JspServlet
            	// 如:servletClass === org.apache.catalina.servlets.DefaultServlet
            	// 如: servletClass === cn.java.note.HelloServlet
                servlet = (Servlet) instanceManager.newInstance(servletClass);//使用实例管理器创建实例,会使用到“名称上下文” -------
                
                // 处理Servlet的安全注解
                processServletSecurityAnnotation(servlet.getClass());
                
                // 调用Servlet的初始化方法init
                initServlet(servlet);

                fireContainerEvent("load", this); // 触发容器事件 ContainerListener
			}
		}
		
		// 默认实例管理器
		class org.apache.catalina.core.DefaultInstanceManager{
			
			// 构造函数
			public DefaultInstanceManager(Context context,
		            Map<String, Map<String, String>> injectionMap,
		            org.apache.catalina.Context catalinaContext,
		            ClassLoader containerClassLoader) {
				 // !!! context === org.apache.naming.NamingContext
		        this.context = context; // 名称上下文
			}
			
			// 创建实例1
			public Object newInstance(String className) throws IllegalAccessException,
		            InvocationTargetException, NamingException, InstantiationException,
		            ClassNotFoundException {
		    	// 加载类,检查是否保护
		        Class<?> clazz = loadClassMaybePrivileged(className, classLoader);
		        return newInstance(clazz.newInstance(), clazz);//名称上下文的使用 -------
		    }
			
			// 创建实例2
			private Object newInstance(Object instance, Class<?> clazz)
		            throws IllegalAccessException, InvocationTargetException, NamingException {
		    	// 不忽略注解
		        if (!ignoreAnnotations) {
		        	// 从Servlet类的继承树中收集Servlet的注解
		            Map<String, String> injections = assembleInjectionsFromClassHierarchy(clazz); // 查看配置的注解列表
//		          分析出类上的注解信息: 包括字段和方法,
//		            @Resource
//		            @WebServiceRef
//		            @PersistenceContext
//		            @PersistenceUnit
//		            @PostConstruct
//		            @PreDestroy
		            populateAnnotationsCache(clazz, injections); 
//		          根据注解说明,调用Servlet的方法,进行设置名称上下文的资源
		            processAnnotations(instance, injections); //名称上下文的使用 -------
//		          设置@PostConstruct/@PreDestroy类型的资源依赖
		            postConstruct(instance, clazz);
		        }
		        return instance;
		    }
			
			// 从“名称上下文”中取得需要注入的资源
			protected void processAnnotations(Object instance, Map<String, String> injections)
		            throws IllegalAccessException, InvocationTargetException, NamingException {
				Class<?> clazz = instance.getClass();

		        while (clazz != null) {
		            AnnotationCacheEntry[] annotations;
		            synchronized (annotationCache) {
		                annotations = annotationCache.get(clazz);
		            }
		            for (AnnotationCacheEntry entry : annotations) {
		                if (entry.getType() == AnnotationCacheEntryType.SETTER) { // 通过setter的反射出来的注解
		                	// context === org.apache.naming.NamingContext  //名称上下文的使用 -------
		                	// 调用Servlet的方法,进行设置资源
		                    lookupMethodResource(context, instance,
		                            getMethod(clazz, entry),
		                            entry.getName(), clazz);
		                } else if (entry.getType() == AnnotationCacheEntryType.FIELD) { // 通过字段反射出来的注解
		                    lookupFieldResource(context, instance,
		                            getField(clazz, entry),
		                            entry.getName(), clazz);
		                }
		            }
		            clazz = clazz.getSuperclass();
		        }
			}
			
			//在名称上下文中查找资源
			protected static void lookupMethodResource(Context context,
		            Object instance, Method method, String name, Class<?> clazz)
		            throws NamingException, IllegalAccessException, InvocationTargetException {

		        Object lookedupResource;
		        boolean accessibility;

		        String normalizedName = normalize(name);

		        // context === org.apache.naming.NamingContext
		        if ((normalizedName != null) && (normalizedName.length() > 0)) {
		            lookedupResource = context.lookup(normalizedName); // 在名称上下文中查找资源 //名称上下文的使用 -------
		        } else {
		            lookedupResource = context.lookup(
		                    clazz.getName() + "/" + Introspection.getPropertyName(method));
		        }

		        synchronized (method) {
		            accessibility = method.isAccessible();
		            method.setAccessible(true);
		            method.invoke(instance, lookedupResource); // 调用Servlet的方法,进行设置资源
		            method.setAccessible(accessibility);
		        }
		    }
		}