/* * 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.container; import net.hasor.core.*; import net.hasor.core.Type; import net.hasor.core.convert.ConverterUtils; import net.hasor.core.info.*; import net.hasor.core.utils.BeanUtils; import net.hasor.core.utils.ExceptionUtils; import net.hasor.core.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.*; import java.util.*; import java.util.Map.Entry; /** * 负责创建Bean对象,以及依赖注入和Aop的实现。 * @version : 2015年6月26日 * @author 赵永春(zyc@hasor.net) */ public abstract class TemplateBeanBuilder implements BeanBuilder { protected Logger logger = LoggerFactory.getLogger(getClass()); /**创建一个AbstractBindInfoProviderAdapter*/ public <T> AbstractBindInfoProviderAdapter<T> createInfoAdapter(Class<T> bindType, Class<?> binderSource) { return new DefaultBindInfoProviderAdapter<T>(bindType); } /** 通过{@link BindInfo}创建Bean。 */ public <T> T getInstance(final BindInfo<T> bindInfo, final AppContext appContext) { Provider<? extends T> instanceProvider = null; Provider<Scope> scopeProvider = null; // //可能存在的 CustomerProvider if (bindInfo instanceof CustomerProvider) { CustomerProvider<? extends T> adapter = (CustomerProvider<T>) bindInfo; instanceProvider = adapter.getCustomerProvider(); } //可能存在的 ScopeProvider if (bindInfo instanceof ScopeProvider) { ScopeProvider adapter = (ScopeProvider) bindInfo; scopeProvider = adapter.getScopeProvider(); } //create Provider. if (instanceProvider == null && bindInfo instanceof AbstractBindInfoProviderAdapter) { instanceProvider = new Provider<T>() { public T get() { Class<T> targetType = bindInfo.getBindType(); Class<T> superType = ((AbstractBindInfoProviderAdapter) bindInfo).getSourceType(); if (superType != null) { targetType = superType; } T targetBean = createObject(targetType, bindInfo, appContext); return targetBean; } }; } else if (instanceProvider == null) { instanceProvider = new Provider<T>() { public T get() { T targetBean = getDefaultInstance(bindInfo.getBindType(), appContext); return targetBean; } }; } //scope if (scopeProvider != null) { instanceProvider = scopeProvider.get().scope(bindInfo, instanceProvider); } return instanceProvider.get(); } /**创建一个未绑定过的类型*/ public <T> T getDefaultInstance(final Class<T> oriType, AppContext appContext) { if (oriType == null) { return null; } T targetBean = createObject(oriType, null, appContext); return targetBean; } // // protected <T> Class<T> findImplClass(Class<T> notSureType) { ImplBy implBy = notSureType.getAnnotation(ImplBy.class); if (implBy == null) { return notSureType; } Class<?> implClass = implBy.value(); if (implClass == notSureType) { return notSureType; } Class<?> implLinkClass = findImplClass(implClass); return (Class<T>) ((implClass == implLinkClass) ? implClass : implLinkClass); } /**创建对象*/ protected <T> T createObject(Class<T> targetType, BindInfo<T> bindInfo, AppContext appContext) { try { // //1.特殊类型创建处理。 targetType = findImplClass(targetType); int modifiers = targetType.getModifiers(); if (targetType.isInterface() || targetType.isEnum() || (modifiers == (modifiers | Modifier.ABSTRACT))) { return null; } if (targetType.isPrimitive()) { return (T) BeanUtils.getDefaultValue(targetType); } if (targetType.isArray()) { Class<?> comType = targetType.getComponentType(); return (T) Array.newInstance(comType, 0); } // //2.准备Aop List<BindInfo<AopBindInfoAdapter>> aopBindList = appContext.findBindingRegister(AopBindInfoAdapter.class); List<AopBindInfoAdapter> aopList = new ArrayList<AopBindInfoAdapter>(); for (BindInfo<AopBindInfoAdapter> info : aopBindList) { aopList.add(this.getInstance(info, appContext)); } // //2.动态代理 ClassLoader rootLosder = appContext.getClassLoader(); Class<?> newType = ClassEngine.buildType(targetType, rootLosder, aopList, appContext); // //3.确定要调用的构造方法。 Constructor<?> constructor = null; Provider<?>[] paramProviders = null; if (bindInfo != null && bindInfo instanceof DefaultBindInfoProviderAdapter) { DefaultBindInfoProviderAdapter<?> defBinder = (DefaultBindInfoProviderAdapter<?>) bindInfo; constructor = defBinder.getConstructor(newType, appContext); paramProviders = defBinder.getConstructorParams(newType, appContext); } else { constructor = newType.getConstructor(); paramProviders = new Provider<?>[0]; } // //4.创建对象。 if (paramProviders == null || paramProviders.length == 0) { T targetBean = (T) constructor.newInstance(); return doInject(targetBean, bindInfo, appContext, newType); } else { Object[] paramObjects = new Object[paramProviders.length]; for (int i = 0; i < paramProviders.length; i++) { paramObjects[i] = paramProviders[i].get(); } T targetBean = (T) constructor.newInstance(paramObjects); return doInject(targetBean, bindInfo, appContext, newType); } } catch (Throwable e) { throw ExceptionUtils.toRuntimeException(e); } } /**执行依赖注入*/ protected <T> T doInject(T targetBean, BindInfo<T> bindInfo, AppContext appContext, Class<?> targetType) throws Throwable { //1.Aware接口的执行 if (bindInfo != null && targetBean instanceof BindInfoAware) { ((BindInfoAware) targetBean).setBindInfo(bindInfo); } if (targetBean instanceof AppContextAware) { ((AppContextAware) targetBean).setAppContext(appContext); } //2.依赖注入 targetType = (targetType == null) ? targetBean.getClass() : targetType; if (targetBean instanceof InjectMembers) { ((InjectMembers) targetBean).doInject(appContext); } else { injectObject(targetBean, bindInfo, appContext, targetType); } //3.Init初始化方法。 initObject(targetBean, bindInfo); // return targetBean; } /**/ private <T> void injectObject(T targetBean, BindInfo<T> bindInfo, AppContext appContext, Class<?> targetType) throws IllegalAccessException { Set<String> injectFileds = new HashSet<String>(); /*a.配置注入*/ if (bindInfo != null && bindInfo instanceof DefaultBindInfoProviderAdapter) { DefaultBindInfoProviderAdapter<?> defBinder = (DefaultBindInfoProviderAdapter<?>) bindInfo; Map<String, Provider<?>> propMaps = defBinder.getPropertys(appContext); for (Entry<String, Provider<?>> propItem : propMaps.entrySet()) { String propertyName = propItem.getKey(); Class<?> propertyType = BeanUtils.getPropertyOrFieldType(targetType, propertyName); boolean canWrite = BeanUtils.canWriteProperty(propertyName, targetType); // if (!canWrite) { String logMsg = "doInject, property " + propertyName + " can not write."; logger.error(logMsg); throw new IllegalStateException(logMsg); } Provider<?> provider = propItem.getValue(); if (provider == null) { String logMsg = "can't injection ,property " + propertyName + " data Provider is null."; logger.error(logMsg); throw new IllegalStateException(logMsg); } // Object propertyVal = ConverterUtils.convert(propertyType, provider.get()); BeanUtils.writePropertyOrField(targetBean, propertyName, propertyVal); injectFileds.add(propertyName); } } /*b.注解注入*/ List<Field> fieldList = BeanUtils.findALLFields(targetType); for (Field field : fieldList) { String name = field.getName(); boolean hasAnno_1 = field.isAnnotationPresent(Inject.class); boolean hasAnno_2 = field.isAnnotationPresent(InjectSettings.class); // if (!hasAnno_1 && !hasAnno_2) { continue; } boolean hasInjected = injectFileds.contains(name); if (hasInjected) { String logMsg = "doInject , " + targetType + " , property " + name + " duplicate."; logger.warn(logMsg); throw new IllegalStateException(logMsg); } if (!field.isAccessible()) { field.setAccessible(true); } // boolean inj = injInject(targetBean, appContext, field);// @Inject if (!inj) { injSettings(targetBean, appContext, field); // @InjectSettings } // injectFileds.add(field.getName()); } } // private <T> boolean injInject(T targetBean, AppContext appContext, Field field) throws IllegalAccessException { Inject inject = field.getAnnotation(Inject.class); if (inject == null) { return false; } Type byType = inject.byType(); Object obj = null; if (StringUtils.isBlank(inject.value())) { obj = appContext.getInstance(field.getType()); } else { /* */ if (Type.ByID == byType) { obj = appContext.getInstance(inject.value()); } else if (Type.ByName == byType) { obj = appContext.findBindingBean(inject.value(), field.getType()); } } if (obj != null) { field.set(targetBean, obj); return true; } else { return false; } } // private <T> boolean injSettings(T targetBean, AppContext appContext, Field field) throws IllegalAccessException { InjectSettings inject = field.getAnnotation(InjectSettings.class); if (inject == null) { return false; } Object obj = null; if (StringUtils.isBlank(inject.value())) { return false; } else { String settingVar = inject.value(); String settingValue = null; if (settingVar.startsWith("${") && settingVar.endsWith("}")) { settingVar = settingVar.substring(2, settingVar.length() - 1); settingValue = appContext.getEnvironment().evalString("%" + settingVar + "%"); } else { settingValue = appContext.getEnvironment().getSettings().getString(inject.value(), inject.defaultValue()); } obj = ConverterUtils.convert(settingValue, field.getType()); } if (obj != null) { field.set(targetBean, obj); return true; } else { return false; } } // private <T> void initObject(T targetBean, BindInfo<T> bindInfo) throws Throwable { try { Method initMethod = findInitMethod(targetBean.getClass(), bindInfo); // if (initMethod != null) { Class<?>[] paramArray = initMethod.getParameterTypes(); Object[] paramObject = BeanUtils.getDefaultValue(paramArray); initMethod.invoke(targetBean, paramObject); } } catch (InvocationTargetException e) { throw e.getTargetException(); } } // /** 查找类的默认初始化方法*/ public static Method findInitMethod(Class<?> targetBeanType, BindInfo<?> bindInfo) { Method initMethod = null; //a.注解形式(注解优先) if (initMethod == null && targetBeanType != null) { List<Method> methodList = BeanUtils.getMethods(targetBeanType); for (Method method : methodList) { boolean hasAnno = method.isAnnotationPresent(Init.class); if (hasAnno) { initMethod = method; break; } } } //b.可能存在的配置。 if (initMethod == null && bindInfo != null && bindInfo instanceof DefaultBindInfoProviderAdapter) { DefaultBindInfoProviderAdapter<?> defBinder = (DefaultBindInfoProviderAdapter<?>) bindInfo; initMethod = defBinder.getInitMethod(targetBeanType); } return initMethod; } /** 检测是否为单例(注解优先)*/ public static boolean testSingleton(Class<?> targetType, BindInfo<?> bindInfo, Settings settings) { Prototype prototype = targetType.getAnnotation(Prototype.class); Singleton singleton = targetType.getAnnotation(Singleton.class); if (prototype != null && singleton != null) { throw new IllegalArgumentException(targetType + " , @Prototype and @Singleton appears only one."); } // boolean isSingleton = false; if (prototype != null) { isSingleton = false; } else if (singleton != null) { isSingleton = true; } else { if (settings != null) { isSingleton = settings.getBoolean("hasor.default.asEagerSingleton", true); } if (bindInfo != null && bindInfo instanceof AbstractBindInfoProviderAdapter) { Boolean sing = ((AbstractBindInfoProviderAdapter) bindInfo).isSingleton(); if (sing != null) { isSingleton = sing; } } } return isSingleton; } }