/*
* Copyright 2008-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.hasor.core.context;
import net.hasor.core.*;
import net.hasor.core.binder.AbstractBinder;
import net.hasor.core.binder.ApiBinderCreater;
import net.hasor.core.binder.ApiBinderInvocationHandler;
import net.hasor.core.binder.BinderHelper;
import net.hasor.core.container.BeanBuilder;
import net.hasor.core.container.BeanContainer;
import net.hasor.core.container.ScopManager;
import net.hasor.core.utils.ExceptionUtils;
import net.hasor.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Proxy;
import java.util.*;
/**
* 抽象类 AbstractAppContext 是 {@link AppContext} 接口的基础实现。
* <p>它包装了大量细节代码,可以方便的通过子类来创建独特的上下文支持。<p>
*
* 提示:initContext 方法是整个类的入口方法。
* @version : 2013-4-9
* @author 赵永春 (zyc@hasor.net)
*/
public abstract class TemplateAppContext implements AppContext {
public static final String DefaultSettings = "hasor-config.xml";
protected Logger logger = LoggerFactory.getLogger(getClass());
private final ShutdownHook shutdownHook = new ShutdownHook(this);
//
/**通过名获取Bean的类型。*/
public Class<?> getBeanType(String bindID) {
Hasor.assertIsNotNull(bindID, "bindID is null.");
BeanContainer container = getContainer();
BindInfo<?> bindInfo = container.findBindInfoByID(bindID);
if (bindInfo != null) {
return bindInfo.getBindType();
}
return null;
}
/** @return 判断是否存在某个ID的绑定。*/
public boolean containsBindID(String bindID) {
Hasor.assertIsNotNull(bindID, "bindID is null.");
BeanContainer container = getContainer();
BindInfo<?> bindInfo = container.findBindInfoByID(bindID);
return bindInfo != null;
}
/** @return 获取已经注册的BeanID。*/
public String[] getBindIDs() {
BeanContainer container = getContainer();
Collection<String> nameList = container.getBindInfoIDs();
if (nameList == null || nameList.isEmpty()) {
return StringUtils.EMPTY_STRING_ARRAY;
}
return nameList.toArray(new String[nameList.size()]);
}
/**如果存在目标类型的Bean则返回Bean的名称。*/
public String[] getNames(final Class<?> targetClass) {
Hasor.assertIsNotNull(targetClass, "targetClass is null.");
BeanContainer container = getContainer();
Collection<String> nameList = container.getBindInfoNamesByType(targetClass);
if (nameList == null || nameList.isEmpty()) {
return StringUtils.EMPTY_STRING_ARRAY;
}
return nameList.toArray(new String[nameList.size()]);
}
/*---------------------------------------------------------------------------------------Bean*/
/**创建Bean。*/
public <T> T getInstance(String bindID) {
Hasor.assertIsNotNull(bindID, "bindID is null.");
BeanContainer container = getContainer();
BindInfo<T> bindInfo = container.findBindInfoByID(bindID);
if (bindInfo != null) {
return this.getInstance(bindInfo);
}
return null;
}
/**创建Bean。*/
public <T> T getInstance(Class<T> targetClass) {
Hasor.assertIsNotNull(targetClass, "targetClass is null.");
Provider<T> provider = this.getProvider(targetClass);
if (provider != null) {
logger.debug("getInstance form getProvider, targetClass is {}.", targetClass);
return provider.get();
} else {
logger.debug("getInstance form getDefaultInstance, targetClass is {}.", targetClass);
return getBeanBuilder().getDefaultInstance(targetClass, this);
}
}
/**创建Bean。*/
public <T> T getInstance(final BindInfo<T> info) {
Provider<T> provider = this.getProvider(info);
if (provider != null) {
return provider.get();
}
return null;
}
/**仅仅执行依赖注入。*/
public <T> T justInject(T object) {
if (object == null) {
return null;
}
return this.justInject(object, object.getClass());
}
/**仅仅执行依赖注入。*/
public <T> T justInject(T object, Class<?> beanType) {
if (object == null || beanType == null) {
return null;
}
try {
return (T) this.getContainer().justInject(object, beanType, this);
} catch (Throwable e) {
throw ExceptionUtils.toRuntimeException(e);
}
}
/**创建Bean。*/
public <T> Provider<T> getProvider(String bindID) {
Hasor.assertIsNotNull(bindID, "bindID is null.");
BeanContainer container = getContainer();
BindInfo<T> bindInfo = container.findBindInfoByID(bindID);
if (bindInfo != null) {
return this.getProvider(bindInfo);
}
return null;
}
/**创建Bean。*/
public <T> Provider<T> getProvider(final Class<T> targetClass) {
Hasor.assertIsNotNull(targetClass, "targetClass is null.");
BindInfo<T> bindInfo = getBindInfo(targetClass);
final AppContext appContext = this;
//
if (bindInfo == null) {
return new Provider<T>() {
public T get() {
return getBeanBuilder().getDefaultInstance(targetClass, appContext);
}
};
} else {
return getProvider(bindInfo);
}
}
/**创建Bean。*/
public <T> Provider<T> getProvider(final BindInfo<T> info) {
if (info == null) {
return null;
}
final AppContext appContext = this;
Provider<T> provider = new Provider<T>() {
public T get() {
return getBeanBuilder().getInstance(info, appContext);
}
};
return provider;
}
;
//
/**获取用于创建Bean的{@link BeanBuilder}*/
protected BeanBuilder getBeanBuilder() {
return getContainer();
}
/**获取用于创建Bean对象的{@link BeanContainer}接口*/
protected abstract BeanContainer getContainer();
//
/*------------------------------------------------------------------------------------Binding*/
/**通过一个类型获取所有绑定到该类型的上的对象实例。*/
public <T> List<T> findBindingBean(final Class<T> bindType) {
Hasor.assertIsNotNull(bindType, "bindType is null.");
//
BeanContainer container = getContainer();
List<BindInfo<T>> typeRegisterList = container.findBindInfoList(bindType);
if (typeRegisterList == null || typeRegisterList.isEmpty()) {
return new ArrayList<T>(0);
}
ArrayList<T> returnData = new ArrayList<T>();
for (BindInfo<T> adapter : typeRegisterList) {
T instance = this.getInstance(adapter);
returnData.add(instance);
}
return returnData;
}
/**通过一个类型获取所有绑定到该类型的上的对象实例。*/
public <T> List<Provider<T>> findBindingProvider(final Class<T> bindType) {
Hasor.assertIsNotNull(bindType, "bindType is null.");
//
BeanContainer container = getContainer();
List<BindInfo<T>> typeRegisterList = container.findBindInfoList(bindType);
if (typeRegisterList == null || typeRegisterList.isEmpty()) {
return new ArrayList<Provider<T>>(0);
}
ArrayList<Provider<T>> returnData = new ArrayList<Provider<T>>();
for (BindInfo<T> adapter : typeRegisterList) {
Provider<T> provider = this.getProvider(adapter);
returnData.add(provider);
}
return returnData;
}
/**通过一个类型获取所有绑定到该类型的上的对象实例。*/
public <T> T findBindingBean(final String withName, final Class<T> bindType) {
Hasor.assertIsNotNull(withName, "withName is null.");
Hasor.assertIsNotNull(bindType, "bindType is null.");
//
BindInfo<T> typeRegister = this.findBindingRegister(withName, bindType);
if (typeRegister != null) {
return this.getInstance(typeRegister);
}
return null;
}
/**通过一个类型获取所有绑定到该类型的上的对象实例。*/
public <T> Provider<T> findBindingProvider(final String withName, final Class<T> bindType) {
Hasor.assertIsNotNull(withName, "withName is null.");
Hasor.assertIsNotNull(bindType, "bindType is null.");
//
BindInfo<T> typeRegister = this.findBindingRegister(withName, bindType);
if (typeRegister != null) {
return this.getProvider(typeRegister);
}
return null;
}
/**根据ID获取{@link BindInfo}。*/
@Override
public <T> BindInfo<T> getBindInfo(String bindID) {
BeanContainer container = getContainer();
return container.findBindInfoByID(bindID);
}
@Override
public <T> BindInfo<T> getBindInfo(Class<T> bindType) {
Hasor.assertIsNotNull(bindType, "bindType is null.");
return getContainer().findBindInfoByType(bindType);
}
/**通过一个类型获取所有绑定到该类型的上的对象实例。*/
@Override
public <T> List<BindInfo<T>> findBindingRegister(Class<T> bindType) {
Hasor.assertIsNotNull(bindType, "bindType is null.");
return getContainer().findBindInfoList(bindType);
}
/**通过一个类型获取所有绑定到该类型的上的对象实例。*/
@Override
public <T> BindInfo<T> findBindingRegister(final String withName, final Class<T> bindType) {
Hasor.assertIsNotNull(withName, "withName is null.");
Hasor.assertIsNotNull(bindType, "bindType is null.");
return getContainer().findBindInfo(withName, bindType);
}
//
/*------------------------------------------------------------------------------------Process*/
/**查找Module(由Module初始化的子Module不再查找范围内)。*/
protected Module[] findModules() {
Environment env = this.getEnvironment();
boolean loadErrorShow = env.getSettings().getBoolean("hasor.modules.loadErrorShow", true);
boolean loadModule = env.getSettings().getBoolean("hasor.modules.loadModule", true);
if (!loadModule) {
return new Module[0];
}
//
ArrayList<Module> moduleList = new ArrayList<Module>();
String[] allModules = env.getSettings().getStringArray("hasor.modules.module");
Set<String> moduleTypeSet = new LinkedHashSet<String>(Arrays.asList(allModules));
for (String moduleType : moduleTypeSet) {
if (StringUtils.isBlank(moduleType))
continue;
//
try {
Class<?> moduleClass = this.getClassLoader().loadClass(moduleType);
moduleList.add((Module) moduleClass.newInstance());
} catch (Throwable e) {
logger.warn("load module Type {} is failure. -> {}:{}", moduleType, e.getClass(), e.getMessage());
if (loadErrorShow) {
logger.error(e.getMessage(), e);
}
}
}
return moduleList.toArray(new Module[moduleList.size()]);
}
/**开始进入初始化过程.*/
protected void doInitialize() throws Throwable {
//
}
/**初始化过程完成.*/
protected void doInitializeCompleted() {
this.getContainer().doInitializeCompleted(getEnvironment());
}
/**开始进入容器启动过程.*/
protected void doStart() {
List<ContextStartListener> listenerList = findBindingBean(ContextStartListener.class);
for (ContextStartListener listener : listenerList) {
listener.doStart(this);
}
}
/**容器启动完成。*/
protected void doStartCompleted() {
List<ContextStartListener> listenerList = findBindingBean(ContextStartListener.class);
for (ContextStartListener listener : listenerList) {
listener.doStartCompleted(this);
}
}
/**开始进入容器停止.*/
protected void doShutdown() {
List<ContextShutdownListener> listenerList = findBindingBean(ContextShutdownListener.class);
for (ContextShutdownListener listener : listenerList) {
listener.doShutdown(this);
}
}
/**容器启动停止。*/
protected void doShutdownCompleted() {
List<ContextShutdownListener> listenerList = findBindingBean(ContextShutdownListener.class);
for (ContextShutdownListener listener : listenerList) {
listener.doShutdownCompleted(this);
}
this.getContainer().doShutdownCompleted();
}
//
/*--------------------------------------------------------------------------------------Utils*/
/**为模块创建ApiBinder。*/
protected ApiBinder newApiBinder() throws Throwable {
//
// .寻找ApiBinder扩展
Map<Class<?>, Class<?>> extBinderMap = new HashMap<Class<?>, Class<?>>();
XmlNode[] nodeArray = this.getEnvironment().getSettings().getXmlNodeArray("hasor.apiBinderSet.binder");
if (nodeArray != null && nodeArray.length > 0) {
for (XmlNode atNode : nodeArray) {
if (atNode == null) {
continue;
}
String binderTypeStr = atNode.getAttribute("type");
String binderImplStr = atNode.getText();
if (StringUtils.isBlank(binderTypeStr) || StringUtils.isBlank(binderImplStr)) {
continue;
}
//
Class<?> binderType = getEnvironment().getClassLoader().loadClass(binderTypeStr);
Class<?> binderImpl = getEnvironment().getClassLoader().loadClass(binderImplStr);
if (!binderType.isInterface()) {
continue;
}
//
extBinderMap.put(binderType, binderImpl);
}
}
//
// .创建扩展
AbstractBinder binder = new AbstractBinder(this.getEnvironment()) {
protected BeanBuilder getBeanBuilder() {
return getContainer();
}
protected ScopManager getScopManager() {
return getContainer();
}
};
Map<Class<?>, Object> implMap = new HashMap<Class<?>, Object>();
for (Map.Entry<Class<?>, Class<?>> ent : extBinderMap.entrySet()) {
Class<?> implKey = ent.getValue();
if (implMap.containsKey(implKey)) {
continue;
}
ApiBinderCreater creater = (ApiBinderCreater) implKey.newInstance();
Object exter = creater.createBinder(binder);
if (exter != null) {
implMap.put(implKey, exter);
}
}
//
// .扩展的映射(这样做的目的是保证不同key应射了同一个实现之后,实现类避免重复初始化)
Map<Class<?>, Object> supportMap = new HashMap<Class<?>, Object>();
supportMap.put(ApiBinder.class, binder);
for (Map.Entry<Class<?>, Class<?>> ent : extBinderMap.entrySet()) {
Object supportVal = implMap.get(ent.getValue());
if (supportVal != null) {
supportMap.put(ent.getKey(), supportVal);
}
}
//
// .返回
Class<?>[] apiArrays = supportMap.keySet().toArray(new Class<?>[supportMap.size()]);
return (ApiBinder) Proxy.newProxyInstance(this.
getClassLoader(), apiArrays, new ApiBinderInvocationHandler(supportMap));
}
/**当完成所有初始化过程之后调用,负责向 Context 绑定一些预先定义的类型。*/
protected void doBind(final ApiBinder apiBinder) {
final AppContext appContet = this;
/*绑定Settings对象的Provider*/
apiBinder.bindType(Settings.class).toProvider(new Provider<Settings>() {
public Settings get() {
return appContet.getEnvironment().getSettings();
}
});
/*绑定EventContext对象的Provider*/
apiBinder.bindType(EventContext.class).toProvider(new Provider<EventContext>() {
public EventContext get() {
return appContet.getEnvironment().getEventContext();
}
});
/*绑定Environment对象的Provider*/
apiBinder.bindType(Environment.class).toProvider(new Provider<Environment>() {
public Environment get() {
return appContet.getEnvironment();
}
});
/*绑定AppContext对象的Provider*/
apiBinder.bindType(AppContext.class).toProvider(new Provider<AppContext>() {
public AppContext get() {
return appContet;
}
});
}
//
/*------------------------------------------------------------------------------------Creater*/
/**
* 确定 AppContext 目前状态是否处于启动状态。
* @return 返回 true 表示已经完成初始化并且启动完成。false表示尚未完成启动过程。
*/
public boolean isStart() {
return this.getContainer().isInit();
}
/**获取环境接口。*/
public abstract Environment getEnvironment();
/**获取当创建Bean时使用的{@link ClassLoader}*/
public ClassLoader getClassLoader() {
return this.getEnvironment().getClassLoader();
}
/**安装模块的工具方法。*/
protected void installModule(ApiBinder apiBinder, Module module) throws Throwable {
if (this.isStart()) {
throw new IllegalStateException("AppContent is started.");
}
if (module == null) {
return;
}
if (logger.isInfoEnabled()) {
logger.info("loadModule " + module.getClass());
}
module.loadModule(apiBinder);
BinderHelper.onInstall(this.getEnvironment(), module);
}
/**
* 模块启动通知,如果在启动期间发生异常,将会抛出该异常。
* @param modules 启动时使用的模块。
* @throws Throwable 启动过程中引发的异常。
*/
public synchronized final void start(Module... modules) throws Throwable {
if (this.isStart()) {
logger.error("appContext is started.");
return;
}
/*1.findModules*/
logger.info("appContext -> findModules.");
ArrayList<Module> findModules = new ArrayList<Module>();
findModules.addAll(Arrays.asList(this.findModules()));
findModules.addAll(Arrays.asList(modules));
/*2.doInitialize*/
logger.info("appContext -> doInitialize.");
doInitialize();
/*3.Bind*/
ApiBinder apiBinder = newApiBinder();
for (Module module : findModules) {
if (module == null)
continue;
this.installModule(apiBinder, module);
}
logger.info("appContext -> doBind.");
doBind(apiBinder);
/*4.引发事件*/
logger.info("appContext -> doInitializeCompleted");
doInitializeCompleted();
//
//-------------------------------------------------------------------------------------------
/*5.Start*/
logger.info("appContext -> doStart");
doStart();
/*6.发送启动事件*/
logger.info("appContext -> fireSyncEvent ,eventType = {}", ContextEvent_Started);
getEnvironment().getEventContext().fireSyncEvent(ContextEvent_Started, this);
logger.info("appContext -> doStartCompleted");
doStartCompleted();/*用于扩展*/
//
/*7.打印状态*/
logger.info("Hasor Started!");
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
/**发送停止通知*/
public synchronized final void shutdown() {
if (!this.isStart()) {
return;
}
EventContext ec = getEnvironment().getEventContext();
/*1.Init*/
logger.info("shutdown - doShutdown.");
doShutdown();
/*2.引发事件*/
logger.info("shutdown - fireSyncEvent.");
try {
ec.fireSyncEvent(ContextEvent_Shutdown, this);
} catch (Throwable throwable) {
/**/
}
logger.info("shutdown - doShutdownCompleted..");
doShutdownCompleted();
logger.info("shutdown - finish.");
try {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
} catch (IllegalStateException e) {
if (!"Shutdown in progress".equals(e.getMessage())) {
logger.error(e.getMessage(), e);
}
}
}
}