名称上下文(用于存放资源、被实例管理用来查找资源是否存在于名称上下文中)
// 名称上下文(用于全局资源、被实例管理用来查找资源是否存在于名称上下文中)
// 名称上下文的创建---------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);
}
}
}