com.github.netty.core.util.ApplicationX Maven / Gradle / Ivy
package com.github.netty.core.util;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.*;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static java.lang.annotation.ElementType.*;
/**
* Lightweight container that supports resource injection
*
* @author wangzihao
* 2016/11/11/011
*/
public class ApplicationX {
private static final AtomicInteger SHUTDOWN_HOOK_ID_INCR = new AtomicInteger();
private static final Method[] EMPTY_METHOD_ARRAY = {};
private static final PropertyDescriptor[] EMPTY_DESCRIPTOR_ARRAY = {};
private static final Constructor CONCURRENT_REFERENCE_MAP_CONSTRUCTOR = getAnyConstructor(
new Class[]{int.class},
"com.github.netty.core.util.ConcurrentReferenceHashMap",
"org.springframework.util.ConcurrentReferenceHashMap",
"org.hibernate.validator.internal.util.ConcurrentReferenceHashMap"
);
private static final Map AUTOWIRED_ANNOTATION_CACHE_MAP = newConcurrentReferenceMap(128);
private static final Map QUALIFIER_ANNOTATION_CACHE_MAP = newConcurrentReferenceMap(128);
private static final Map FACTORY_METHOD_ANNOTATION_CACHE_MAP = newConcurrentReferenceMap(32);
private static final Map PROPERTY_DESCRIPTOR_CACHE_MAP = newConcurrentReferenceMap(128);
private static final Map DECLARED_METHODS_CACHE_MAP = newConcurrentReferenceMap(128);
private static final OrderComparator COMPARATOR = new OrderComparator(new LinkedHashSet<>(Collections.singletonList(Order.class)));
private final Collection> initMethodAnnotations = new LinkedHashSet<>(
Arrays.asList(PostConstruct.class));
private final Collection> destroyMethodAnnotations = new LinkedHashSet<>(
Arrays.asList(PreDestroy.class));
private final Collection> scannerAnnotations = new LinkedHashSet<>(
Arrays.asList(Resource.class, Component.class));
private final Collection> autowiredAnnotations = new LinkedHashSet<>(
Arrays.asList(Resource.class, Autowired.class));
private final Collection> qualifierAnnotations = new LinkedHashSet<>(
Arrays.asList(Resource.class, Qualifier.class));
private final Collection> orderedAnnotations = new LinkedHashSet<>(
Arrays.asList(Order.class));
private final Collection> factoryMethodAnnotations = new LinkedHashSet<>(
Arrays.asList(Bean.class));
//BeanPostProcessor接口是为了将每个bean的处理阶段的处理, 抽象成接口, 让用户可以根据不同需求不同处理. 比如自动注入,AOP,定时任务,异步注解,servlet注入,错误页注册
private final Collection beanPostProcessors = new TreeSet<>(new OrderComparator(orderedAnnotations));
//需要跳过生命周期管理的bean名称集合
private final Collection beanSkipLifecycles = new LinkedHashSet<>(8);
//存放Class与bean名称对应关系
private final Map beanNameMap = new ConcurrentHashMap<>(64);
//存放别名与别名关系或别名与bean名称的关系
private final Map beanAliasMap = new ConcurrentHashMap<>(6);
//存放bean名称与bean描述的关系
private final Map beanDefinitionMap = new ConcurrentHashMap<>(64);
//存放bean名称与单例对象的关系
private final Map singletonObjects = new ConcurrentHashMap<>(64);
//正在创建的单例bean
private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
private final Map beanFactoryMap = new LinkedHashMap<>(8);
private final AbstractBeanFactory defaultBeanFactory = new DefaultBeanFactory();
private final Scanner scanner = new Scanner();
private final long timestamp = System.currentTimeMillis();
private BiPredicate resourceLoaderUrlFilter = (classLoader, url) -> !isJavaLib(url);
private Supplier resourceLoader;
private Function beanNameGenerator = new DefaultBeanNameGenerator(this);
public ApplicationX() {
this(ApplicationX.class::getClassLoader);
}
public ApplicationX(Supplier resourceLoader) {
this.resourceLoader = Objects.requireNonNull(resourceLoader);
addClasses(initMethodAnnotations,
"javax.annotation.PostConstruct");
addClasses(destroyMethodAnnotations,
"javax.annotation.PreDestroy");
addClasses(scannerAnnotations,
"javax.annotation.Resource",
"org.springframework.stereotype.Component");
addClasses(autowiredAnnotations,
"javax.annotation.Resource",
"javax.inject.Inject",
"org.springframework.beans.factory.annotation.Autowired");
addClasses(qualifierAnnotations,
"javax.annotation.Resource",
"org.springframework.beans.factory.annotation.Qualifier");
addClasses(orderedAnnotations,
"org.springframework.core.annotation.Order");
addSingletonBean(this);
addBeanPostProcessor(new RegisteredBeanPostProcessor(this));
addBeanPostProcessor(new AutowiredConstructorPostProcessor(this));
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdownHook, "app.shutdownHook-" + SHUTDOWN_HOOK_ID_INCR.getAndIncrement()));
}
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
ApplicationX app = new ApplicationX();
System.out.println("new = " + (System.currentTimeMillis() - startTime) + "/ms");
startTime = System.currentTimeMillis();
int count = app.scanner("com.github.netty").inject();
System.out.println("scanner = " + (System.currentTimeMillis() - startTime) + "/ms");
System.out.println("count = " + count);
System.out.println("app = " + app);
}
private static boolean isAbstract(Class clazz) {
int modifier = clazz.getModifiers();
return Modifier.isInterface(modifier) || Modifier.isAbstract(modifier);
}
private static Boolean isExistAnnotation0(Class clazz, Collection> finds, Map cacheMap) {
Annotation annotation;
Boolean exist = cacheMap.get(clazz);
if (finds.contains(clazz)) {
exist = Boolean.TRUE;
} else if (exist == null) {
exist = Boolean.FALSE;
cacheMap.put(clazz, exist);
Queue queue = new LinkedList<>(Arrays.asList(clazz.getDeclaredAnnotations()));
while ((annotation = queue.poll()) != null) {
Class extends Annotation> annotationType = annotation.annotationType();
if (annotationType == clazz) {
continue;
}
if (finds.contains(annotationType)) {
exist = Boolean.TRUE;
break;
}
if (isExistAnnotation0(annotationType, finds, cacheMap)) {
exist = Boolean.TRUE;
break;
}
}
}
cacheMap.put(clazz, exist);
return exist;
}
public static boolean isExistAnnotation(Class clazz, Collection> finds, Map cacheMap) {
Boolean existAnnotation = cacheMap.get(clazz);
if (existAnnotation == null) {
Map tempCacheMap = new HashMap<>();
existAnnotation = isExistAnnotation0(clazz, finds, tempCacheMap);
cacheMap.putAll(tempCacheMap);
}
return existAnnotation;
}
private static T getAnnotationValue(Annotation annotation, String[] fieldNames, Class type) {
for (String fieldName : fieldNames) {
T value = getAnnotationValue(annotation, fieldName, type);
if (value != null) {
return value;
}
}
return null;
}
private static T getAnnotationValue(Annotation annotation, String fieldName, Class type) {
try {
Method method = annotation.annotationType().getDeclaredMethod(fieldName);
Object value = method.invoke(annotation);
if (value != null && type.isAssignableFrom(value.getClass())) {
return (T) value;
} else {
return null;
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
return null;
}
}
private static Annotation findDeclaredAnnotation(AnnotatedElement element, Collection> finds, Map cacheMap) {
Annotation[] fieldAnnotations = element.getDeclaredAnnotations();
for (Annotation annotation : fieldAnnotations) {
boolean existAnnotation = isExistAnnotation(annotation.annotationType(), finds, cacheMap);
if (existAnnotation) {
return annotation;
}
}
return null;
}
private static Annotation findAnnotation(Class rootClass, Collection> finds) {
if (rootClass == null) {
return null;
}
Annotation result;
//类上找
for (Class clazz = rootClass; clazz != null && clazz != Object.class; clazz = clazz.getSuperclass()) {
for (Class extends Annotation> find : finds) {
if (null != (result = clazz.getAnnotation(find))) {
return result;
}
}
}
//接口上找
Collection interfaces = getInterfaces(rootClass);
for (Class i : interfaces) {
for (Class clazz = i; clazz != null; clazz = clazz.getSuperclass()) {
for (Class extends Annotation> find : finds) {
if (null != (result = clazz.getAnnotation(find))) {
return result;
}
}
}
}
return null;
}
private static Collection getInterfaces(Class sourceClass) {
Set interfaceList = new LinkedHashSet<>();
if (sourceClass.isInterface()) {
interfaceList.add(sourceClass);
}
for (Class currClass = sourceClass; currClass != null && currClass != Object.class; currClass = currClass.getSuperclass()) {
Collections.addAll(interfaceList, currClass.getInterfaces());
}
return interfaceList;
}
private static boolean isSimpleProperty(Class> clazz) {
return isSimpleValueType(clazz) || (clazz.isArray() && isSimpleValueType(clazz.getComponentType()));
}
private static boolean isSimpleValueType(Class> clazz) {
return (clazz.isPrimitive() ||
clazz == Character.class ||
Enum.class.isAssignableFrom(clazz) ||
CharSequence.class.isAssignableFrom(clazz) ||
Number.class.isAssignableFrom(clazz) ||
Date.class.isAssignableFrom(clazz) ||
URI.class == clazz || URL.class == clazz ||
Locale.class == clazz || Class.class == clazz);
}
private static String findMethodNameByNoArgs(Class clazz, Collection> methodAnnotations) {
for (Method method : clazz.getMethods()) {
if (method.getDeclaringClass() == Object.class
|| method.getReturnType() != void.class
|| method.getParameterCount() != 0) {
continue;
}
for (Class extends Annotation> aClass : methodAnnotations) {
if (method.getAnnotationsByType(aClass).length == 0) {
continue;
}
if (method.getParameterCount() != 0) {
throw new IllegalStateException("method does not have parameters. class=" + clazz + ",method=" + method);
}
return method.getName();
}
}
return null;
}
private static PropertyDescriptor[] getPropertyDescriptorsIfCache(Class clazz) throws IllegalStateException {
PropertyDescriptor[] result = PROPERTY_DESCRIPTOR_CACHE_MAP.get(clazz);
if (result == null) {
try {
BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class, Introspector.USE_ALL_BEANINFO);
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
if (descriptors != null) {
result = descriptors;
} else {
result = EMPTY_DESCRIPTOR_ARRAY;
}
PROPERTY_DESCRIPTOR_CACHE_MAP.put(clazz, result);
} catch (IntrospectionException e) {
throw new IllegalStateException("getPropertyDescriptors error. class=" + clazz + e, e);
}
// TODO: 1月28日 028 getPropertyDescriptorsIfCache
// skip GenericTypeAwarePropertyDescriptor leniently resolves a set* write method
// against a declared read method, so we prefer read method descriptors here.
}
return result;
}
private static ConcurrentMap newConcurrentReferenceMap(int initialCapacity) {
if (CONCURRENT_REFERENCE_MAP_CONSTRUCTOR != null) {
try {
return CONCURRENT_REFERENCE_MAP_CONSTRUCTOR.newInstance(initialCapacity);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
//skip
}
}
return new ConcurrentHashMap<>(initialCapacity);
}
private static Method[] getDeclaredMethods(Class> clazz) {
Objects.requireNonNull(clazz);
Method[] result = DECLARED_METHODS_CACHE_MAP.get(clazz);
if (result == null) {
try {
Method[] declaredMethods = clazz.getDeclaredMethods();
List defaultMethods = findConcreteMethodsOnInterfaces(clazz);
if (defaultMethods != null) {
result = new Method[declaredMethods.length + defaultMethods.size()];
System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length);
int index = declaredMethods.length;
for (Method defaultMethod : defaultMethods) {
result[index] = defaultMethod;
index++;
}
} else {
result = declaredMethods;
}
DECLARED_METHODS_CACHE_MAP.put(clazz, (result.length == 0 ? EMPTY_METHOD_ARRAY : result));
} catch (Throwable ex) {
throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() +
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
}
}
return result;
}
private static List findConcreteMethodsOnInterfaces(Class> clazz) {
List result = null;
for (Class> ifc : clazz.getInterfaces()) {
for (Method ifcMethod : ifc.getMethods()) {
if (!Modifier.isAbstract(ifcMethod.getModifiers())) {
if (result == null) {
result = new ArrayList<>();
}
result.add(ifcMethod);
}
}
}
return result;
}
private static void eachClass(Class> clazz, Consumer consumer) {
// Keep backing up the inheritance hierarchy.
consumer.accept(clazz);
Class> superclass = clazz.getSuperclass();
if (superclass != null && superclass != Object.class) {
eachClass(superclass, consumer);
} else if (clazz.isInterface()) {
for (Class> superIfc : clazz.getInterfaces()) {
eachClass(superIfc, consumer);
}
}
}
private static Constructor getAnyConstructor(Class>[] parameterTypes, String... referenceMaps) {
for (String s : referenceMaps) {
try {
Class aClass = (Class) Class.forName(s);
return aClass.getDeclaredConstructor(parameterTypes);
} catch (ClassNotFoundException | NoSuchMethodException e) {
//skip
}
}
return null;
}
public long getTimestamp() {
return timestamp;
}
private void addClasses(Collection annotationList, String... classNames) {
ClassLoader classLoader = resourceLoader.get();
for (String className : classNames) {
try {
annotationList.add(Class.forName(className, false, classLoader));
} catch (Exception e) {
//skip
}
}
}
public Object addSingletonBean(Object instance) {
return addSingletonBean(instance, null, true, null);
}
public Object addSingletonBean(Object instance, String beanName) {
return addSingletonBean(instance, beanName, true, null);
}
public Object addSingletonBean(Object instance, String beanName, boolean isLifecycle) {
return addSingletonBean(instance, beanName, isLifecycle, null);
}
public Object addSingletonBean(Object instance, String beanName, boolean isLifecycle, BiConsumer beanDefinitionConfig) {
Class beanType = instance.getClass();
BeanDefinition definition = newBeanDefinition(beanType);
definition.setBeanSupplier(() -> instance);
if (!isLifecycle) {
beanSkipLifecycles.add(beanName);
}
if (beanName == null) {
beanName = beanNameGenerator.apply(definition);
}
if (beanDefinitionConfig != null) {
beanDefinitionConfig.accept(beanName, definition);
}
definition.setScope(BeanDefinition.SCOPE_SINGLETON);
addBeanDefinition(beanName, definition);
Object oldInstance = singletonObjects.remove(beanName);
if (!definition.isLazyInit()) {
getBean(beanName, null, true);
}
return oldInstance;
}
/**
* 注册别名
*
* @param name bean名称
* @param alias 别名
*/
public void registerAlias(String name, String alias) {
Objects.requireNonNull(name, "'name' must not be empty");
Objects.requireNonNull(alias, "'alias' must not be empty");
synchronized (this.beanAliasMap) {
if (alias.equals(name)) {
this.beanAliasMap.remove(alias);
} else {
String registeredName = this.beanAliasMap.get(alias);
if (registeredName != null && registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
if (hasAlias(alias, name)) {
throw new IllegalStateException("Cannot register alias '" + alias +
"' for name '" + name + "': Circular reference - '" +
name + "' is a direct or indirect alias for '" + alias + "' already");
}
this.beanAliasMap.put(alias, name);
}
}
}
public boolean hasAlias(String name, String alias) {
for (Map.Entry entry : this.beanAliasMap.entrySet()) {
String registeredName = entry.getValue();
if (registeredName.equals(name)) {
String registeredAlias = entry.getKey();
if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
return true;
}
}
}
return false;
}
public void removeAlias(String alias) {
synchronized (this.beanAliasMap) {
String name = this.beanAliasMap.remove(alias);
if (name == null) {
throw new IllegalStateException("No alias '" + alias + "' registered");
}
}
}
public boolean isAlias(String name) {
return this.beanAliasMap.containsKey(name);
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
protected void addSingleton(String beanName, Object singletonObject) {
this.singletonObjects.put(beanName, singletonObject);
}
/**
* 确定原始名称,解析别名规范名称。
*
* @param beanNameOrAlias 用户指定的名称
* @return beanName
*/
public String getBeanName(String beanNameOrAlias) {
String canonicalName = beanNameOrAlias;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.beanAliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
} while (resolvedName != null);
return canonicalName;
}
public String[] getAliases(String name) {
List result = new ArrayList<>();
synchronized (this.beanAliasMap) {
retrieveAliases(name, result);
}
return result.toArray(new String[0]);
}
private void retrieveAliases(String name, List result) {
for (Map.Entry entry : beanAliasMap.entrySet()) {
String alias = entry.getKey();
String registeredName = entry.getValue();
if (registeredName.equals(name)) {
result.add(alias);
retrieveAliases(alias, result);
}
}
}
protected BiConsumer newScannerConsumer(ClassLoader classLoader, ScannerResult result) {
return (url, className) -> {
try {
result.classCount.incrementAndGet();
Class clazz = Class.forName(className, false, classLoader);
if (clazz.isAnnotation()) {
return;
}
// TODO: 1月27日 027 doScan skip interface impl by BeanPostProcessor
if (clazz.isInterface()) {
return;
}
if (!isExistAnnotation(clazz, scannerAnnotations, result.scannerAnnotationCacheMap)) {
return;
}
BeanDefinition definition = newBeanDefinition(clazz);
String beanName = beanNameGenerator.apply(definition);
result.beanDefinitionMap.put(beanName, definition);
} catch (ReflectiveOperationException | LinkageError e) {
//skip
}
};
}
public ScannerResult scanner(ClassLoader classLoader, boolean onlyInMyProject) {
return scanner(classLoader, onlyInMyProject, new ScannerResult());
}
public ScannerResult scanner(ClassLoader classLoader, boolean onlyInMyProject, ScannerResult result) {
result.scannerBeginTimestamp = System.currentTimeMillis();
try {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//只在我的项目中搜索类
if (onlyInMyProject) {
result.classLoaders.add(classLoader);
BiConsumer consumer = newScannerConsumer(classLoader, result);
try {
for (String rootPackage : scanner.getRootPackages()) {
scanner.doScan(rootPackage, classLoader, consumer);
}
} catch (IOException e) {
throw new IllegalStateException("scanner classLoader=" + classLoader + ",error=" + e, e);
}
return result;
}
//获取用户自定义路径url
for (ClassLoader userLoader = classLoader; userLoader != null && userLoader != systemClassLoader; userLoader = userLoader.getParent()) {
if (!(userLoader instanceof URLClassLoader)) {
continue;
}
URL[] urls = ((URLClassLoader) userLoader).getURLs();
if (urls == null) {
continue;
}
for (URL url : urls) {
result.addClassUrl(userLoader, url);
}
}
//扫描所有用户自定义加载器jar包路径
for (URL url : result.tempUrls) {
BiConsumer consumer = newScannerConsumer(classLoader, result);
try {
for (String rootPackage : scanner.getRootPackages()) {
scanner.doScan(rootPackage, null, url, consumer);
}
} catch (IOException e) {
throw new IllegalStateException("scanner userClassLoader error. url=" + url + ",error=" + e, e);
}
}
result.tempUrls.clear();
//扫描系统类加载器的jar包路径
String cp = System.getProperty("java.class.path");
if (cp != null) {
while (cp.length() > 0) {
int pathSepIdx = cp.indexOf(File.pathSeparatorChar);
String pathElem;
if (pathSepIdx < 0) {
pathElem = cp;
addClassURL(result, systemClassLoader, pathElem);
break;
} else if (pathSepIdx > 0) {
pathElem = cp.substring(0, pathSepIdx);
addClassURL(result, systemClassLoader, pathElem);
}
cp = cp.substring(pathSepIdx + 1);
}
for (URL url : result.tempUrls) {
BiConsumer consumer = newScannerConsumer(systemClassLoader, result);
try {
for (String rootPackage : scanner.getRootPackages()) {
scanner.doScan(rootPackage, null, url, consumer);
}
} catch (IOException e) {
throw new IllegalStateException("scanner systemClassLoader error. url=" + url + ",error=" + e, e);
}
}
result.tempUrls.clear();
}
} finally {
result.scannerEndTimestamp = System.currentTimeMillis();
}
return result;
}
protected void addClassURL(ScannerResult result, ClassLoader loader, String path) {
try {
URL url = new File(path).getCanonicalFile().toURI().toURL();
result.addClassUrl(loader, url);
} catch (IOException e) {
e.printStackTrace();
}
}
public BiPredicate getResourceLoaderUrlFilter() {
return resourceLoaderUrlFilter;
}
public void setResourceLoaderUrlFilter(BiPredicate resourceLoaderUrlFilter) {
this.resourceLoaderUrlFilter = resourceLoaderUrlFilter;
}
protected boolean isJavaLib(URL url) {
String urlStr = url.toString();
String[] javaPaths = {"/jre/lib/"};
for (String javaPath : javaPaths) {
if (urlStr.contains(javaPath)) {
return true;
}
}
return false;
}
public ScannerResult scanner(String... rootPackage) {
return scanner(false, rootPackage);
}
public ScannerResult scanner(boolean onlyInMyProject, String... rootPackage) {
addScanPackage(rootPackage);
ClassLoader loader = resourceLoader.get();
return scanner(loader, onlyInMyProject);
}
public ApplicationX addExcludesPackage(String... excludesPackages) {
if (excludesPackages != null) {
scanner.getExcludes().addAll(Arrays.asList(excludesPackages));
}
return this;
}
public ApplicationX addScanPackage(String... rootPackages) {
if (rootPackages != null) {
scanner.getRootPackages().addAll(Arrays.asList(rootPackages));
}
return this;
}
public ApplicationX removeScanPackage(String... rootPackages) {
if (rootPackages != null) {
scanner.getRootPackages().removeAll(Arrays.asList(rootPackages));
}
return this;
}
public ApplicationX addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
beanPostProcessors.add(beanPostProcessor);
return this;
}
public ApplicationX addBeanFactory(Class type, AbstractBeanFactory beanFactory) {
addSingletonBean(beanFactory);
beanFactoryMap.put(type, beanFactory);
return this;
}
public BeanDefinition[] getBeanDefinitions(Class clazz) {
String[] beanNames = beanNameMap.get(clazz);
BeanDefinition[] beanDefinitions = new BeanDefinition[beanNames.length];
for (int i = 0; i < beanNames.length; i++) {
beanDefinitions[i] = getBeanDefinition(beanNames[i]);
}
return beanDefinitions;
}
public BeanDefinition getBeanDefinition(String beanName) {
BeanDefinition definition = beanDefinitionMap.get(beanName);
return definition;
}
public String[] getBeanNamesForType(Class clazz) {
Collection result = new ArrayList<>();
for (Map.Entry entry : beanDefinitionMap.entrySet()) {
BeanDefinition definition = entry.getValue();
if (clazz.isAssignableFrom(definition.getBeanClassIfResolve(resourceLoader))) {
String beanName = entry.getKey();
result.add(beanName);
}
}
return result.toArray(new String[0]);
}
public T getBean(Class clazz) {
return getBean(clazz, null, true);
}
public T getBean(Class clazz, Object[] args, boolean required) {
String[] beanNames = getBeanNamesForType(clazz);
String beanName;
if (beanNames.length == 0) {
if (required) {
throw new IllegalStateException("Not found bean. by type=" + clazz);
} else {
return null;
}
} else if (beanNames.length == 1) {
beanName = beanNames[0];
} else {
List primaryBeanNameList = new ArrayList<>(beanNames.length);
List nonPrimaryBeanNameList = new ArrayList<>(beanNames.length);
for (String eachBeanName : beanNames) {
BeanDefinition definition = getBeanDefinition(eachBeanName);
if (definition.isPrimary()) {
primaryBeanNameList.add(eachBeanName);
} else {
nonPrimaryBeanNameList.add(eachBeanName);
}
}
if (primaryBeanNameList.isEmpty()) {
if (nonPrimaryBeanNameList.size() == 1) {
beanName = nonPrimaryBeanNameList.get(0);
} else {
throw new IllegalStateException("Found more bean. you can Annotation @Primary. beanNames=" + nonPrimaryBeanNameList);
}
} else if (primaryBeanNameList.size() == 1) {
beanName = primaryBeanNameList.get(0);
} else {
throw new IllegalStateException("Found more primary bean. beanNames=" + primaryBeanNameList);
}
}
return getBean(beanName, args, required);
}
public T getBean(String beanNameOrAlias, Object[] args, boolean required) {
String beanName = getBeanName(beanNameOrAlias);
BeanDefinition definition = beanDefinitionMap.get(beanName);
if (definition == null) {
if (required) {
throw new IllegalStateException("getBean error. bean is not definition. beanName=" + beanName);
} else {
return null;
}
}
boolean isSingleton = definition.isSingleton();
Object instance = null;
if (isSingleton) {
instance = singletonObjects.get(beanName);
}
if (instance == null) {
if (isSingleton) {
beforeSingletonCreation(beanName);
}
try {
Class beanClass = definition.getBeanClassIfResolve(resourceLoader);
AbstractBeanFactory beanFactory = getBeanFactory(beanClass);
instance = beanFactory.createBean(beanName, definition, args);
if (isSingleton) {
addSingleton(beanName, instance);
}
} finally {
if (isSingleton) {
afterSingletonCreation(beanName);
}
}
}
return (T) instance;
}
public T getBean(String beanName) {
return (T) getBean(beanName, null, true);
}
public T getBean(String beanName, Object[] args) {
return (T) getBean(beanName, args, true);
}
public List getBeanForAnnotation(Class extends Annotation>... annotationType) {
List result = new ArrayList<>();
for (Map.Entry entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition definition = entry.getValue();
Class beanClass = definition.getBeanClassIfResolve(resourceLoader);
Annotation annotation = findAnnotation(beanClass, Arrays.asList(annotationType));
if (annotation != null) {
T bean = getBean(beanName, null, false);
if (bean != null) {
result.add(bean);
}
}
}
return result;
}
public List getBeanForType(Class clazz) {
List result = new ArrayList<>();
for (String beanName : getBeanNamesForType(clazz)) {
T bean = getBean(beanName, null, false);
if (bean != null) {
result.add(bean);
}
}
return result;
}
public boolean containsBean(String name) {
String beanName = getBeanName(name);
return singletonObjects.containsKey(beanName) || beanDefinitionMap.containsKey(beanName);
}
public boolean containsInstance(String name) {
String beanName = getBeanName(name);
return singletonObjects.containsKey(beanName);
}
public BeanDefinition newBeanDefinition(Class beanType) {
return newBeanDefinition(beanType, beanType);
}
public BeanDefinition newBeanDefinition(Class beanType, AnnotatedElement annotatedElement) {
Lazy lazyAnnotation = annotatedElement.getAnnotation(Lazy.class);
Scope scopeAnnotation = annotatedElement.getAnnotation(Scope.class);
Primary primaryAnnotation = annotatedElement.getAnnotation(Primary.class);
BeanDefinition definition = new BeanDefinition();
definition.setBeanClass(beanType);
definition.setBeanClassName(beanType.getName());
definition.setScope(scopeAnnotation == null ? BeanDefinition.SCOPE_SINGLETON : scopeAnnotation.value());
definition.setLazyInit(lazyAnnotation != null && lazyAnnotation.value());
definition.setInitMethodName(findMethodNameByNoArgs(beanType, initMethodAnnotations));
definition.setDestroyMethodName(findMethodNameByNoArgs(beanType, destroyMethodAnnotations));
definition.setPrimary(primaryAnnotation != null);
return definition;
}
public BeanDefinition addBeanDefinition(String beanName, BeanDefinition definition) {
return addBeanDefinition(beanName, definition, beanNameMap, beanDefinitionMap);
}
public BeanDefinition addBeanDefinition(String beanName, BeanDefinition definition,
Map beanNameMap,
Map beanDefinitionMap) {
Class beanClass = definition.getBeanClassIfResolve(resourceLoader);
String[] oldBeanNames = beanNameMap.get(beanClass);
Set nameSet = oldBeanNames != null ? new LinkedHashSet<>(Arrays.asList(oldBeanNames)) : new LinkedHashSet<>(1);
nameSet.add(beanName);
beanNameMap.put(beanClass, nameSet.toArray(new String[0]));
return beanDefinitionMap.put(beanName, definition);
}
/**
* Callback after singleton creation.
* The default implementation marks the singleton as not in creation anymore.
*
* @param beanName the name of the singleton that has been created
* @see #isSingletonCurrentlyInCreation
*/
protected void afterSingletonCreation(String beanName) {
if (!this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
/**
* Callback before singleton creation.
*
The default implementation register the singleton as currently in creation.
*
* @param beanName the name of the singleton about to be created
* @see #isSingletonCurrentlyInCreation
*/
protected void beforeSingletonCreation(String beanName) {
if (!this.singletonsCurrentlyInCreation.add(beanName)) {
throw new IllegalStateException("BeanCurrentlyInCreationException " + beanName);
}
}
protected int findAutowireType(AnnotatedElement field) {
int autowireType;
Annotation qualifierAnnotation = findDeclaredAnnotation(field, qualifierAnnotations, QUALIFIER_ANNOTATION_CACHE_MAP);
if (qualifierAnnotation != null) {
if (Objects.equals(Resource.class.getSimpleName(), qualifierAnnotation.annotationType().getSimpleName())) {
String autowiredBeanName = getAnnotationValue(qualifierAnnotation, "name", String.class);
autowireType = (autowiredBeanName == null || autowiredBeanName.isEmpty()) ?
BeanDefinition.AUTOWIRE_BY_TYPE : BeanDefinition.AUTOWIRE_BY_NAME;
} else {
autowireType = BeanDefinition.AUTOWIRE_BY_NAME;
}
} else {
autowireType = BeanDefinition.AUTOWIRE_BY_TYPE;
}
return autowireType;
}
protected Object initializeBean(String beanName, BeanWrapper beanWrapper, BeanDefinition definition) throws IllegalStateException {
Object bean = beanWrapper.getWrappedInstance();
invokeBeanAwareMethods(beanName, bean, definition);
Object wrappedBean = bean;
wrappedBean = applyBeanBeforeInitialization(beanName, wrappedBean);
invokeBeanInitialization(beanName, bean, definition);
wrappedBean = applyBeanAfterInitialization(beanName, wrappedBean);
return wrappedBean;
}
protected void invokeBeanAwareMethods(String beanName, Object bean, BeanDefinition definition) throws IllegalStateException {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof ApplicationAware) {
((ApplicationAware) bean).setApplication(this);
}
}
}
protected Object applyBeanBeforeInitialization(String beanName, Object bean) throws IllegalStateException {
Object result = bean;
for (BeanPostProcessor processor : new ArrayList<>(beanPostProcessors)) {
Object current;
try {
current = processor.postProcessBeforeInitialization(result, beanName);
} catch (Exception e) {
throw new IllegalStateException("applyBeanBeforeInitialization error=" + e, e);
}
if (current == null) {
return result;
}
result = current;
}
return result;
}
private Object applyBeanAfterInitialization(String beanName, Object bean) throws IllegalStateException {
Object result = bean;
for (BeanPostProcessor processor : new ArrayList<>(beanPostProcessors)) {
Object current;
try {
current = processor.postProcessAfterInitialization(result, beanName);
} catch (Exception e) {
throw new IllegalStateException("applyBeanAfterInitialization error=" + e, e);
}
if (current == null) {
return result;
}
result = current;
}
return result;
}
private AbstractBeanFactory getBeanFactory(Class beanType) {
AbstractBeanFactory beanFactory = null;
if (beanFactoryMap.size() > 0) {
for (Class type = beanType; type != null; type = type.getSuperclass()) {
beanFactory = beanFactoryMap.get(type);
if (beanFactory != null) {
break;
}
}
}
if (beanFactory == null) {
beanFactory = defaultBeanFactory;
}
return beanFactory;
}
@Override
public String toString() {
return scanner.getRootPackages() + " @ size = " + beanDefinitionMap.size();
}
private void shutdownHook() {
for (Map.Entry entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition definition = entry.getValue();
try {
if (containsInstance(beanName) && isLifecycle(beanName)) {
Object bean = getBean(beanName, null, false);
if (bean == null) {
continue;
}
invokeBeanDestroy(beanName, bean, definition);
}
} catch (Exception e) {
//skip
}
}
}
private void invokeBeanDestroy(String beanName, Object bean, BeanDefinition definition) throws IllegalStateException {
boolean isDisposableBean = bean instanceof DisposableBean;
if (isDisposableBean) {
try {
((DisposableBean) bean).destroy();
} catch (Exception e) {
throw new IllegalStateException("invokeBeanDestroy destroy beanName=" + beanName + ".error=" + e, e);
}
}
String destroyMethodName = definition.getDestroyMethodName();
if (destroyMethodName != null && destroyMethodName.length() > 0 &&
!(isDisposableBean && "destroy".equals(destroyMethodName))) {
Class> beanClass = definition.getBeanClassIfResolve(resourceLoader);
try {
beanClass.getMethod(destroyMethodName).invoke(bean);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new IllegalStateException("invokeBeanDestroy destroyMethodName beanName=" + beanName + ",destroyMethodName" + destroyMethodName + ",error=" + e, e);
}
}
}
private void invokeBeanInitialization(String beanName, Object bean, BeanDefinition definition) throws IllegalStateException {
boolean isInitializingBean = bean instanceof InitializingBean;
if (isInitializingBean) {
try {
((InitializingBean) bean).afterPropertiesSet();
} catch (Exception e) {
throw new IllegalStateException("invokeBeanInitialization afterPropertiesSet beanName=" + beanName + ".error=" + e, e);
}
}
String initMethodName = definition.getInitMethodName();
if (initMethodName != null && initMethodName.length() > 0 &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName))) {
Class> beanClass = definition.getBeanClassIfResolve(resourceLoader);
try {
beanClass.getMethod(initMethodName).invoke(bean);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new IllegalStateException("invokeBeanInitialization initMethodName beanName=" + beanName + ",initMethodName" + initMethodName + ",error=" + e, e);
}
}
}
public String[] getBeanNames() {
return beanDefinitionMap.keySet().toArray(new String[0]);
}
public Collection> getInitMethodAnnotations() {
return initMethodAnnotations;
}
public Collection> getScannerAnnotations() {
return scannerAnnotations;
}
public Collection> getAutowiredAnnotations() {
return autowiredAnnotations;
}
public Collection> getQualifierAnnotations() {
return qualifierAnnotations;
}
public Collection> getDestroyMethodAnnotations() {
return destroyMethodAnnotations;
}
public Collection> getOrderedAnnotations() {
return orderedAnnotations;
}
public Collection> getFactoryMethodAnnotations() {
return factoryMethodAnnotations;
}
public Collection getBeanPostProcessors() {
return beanPostProcessors;
}
public Collection getBeanSkipLifecycles() {
return beanSkipLifecycles;
}
public Function getBeanNameGenerator() {
return beanNameGenerator;
}
public void setBeanNameGenerator(Function beanNameGenerator) {
this.beanNameGenerator = beanNameGenerator;
}
public boolean isLifecycle(String beanName) {
return !beanSkipLifecycles.contains(beanName);
}
public Supplier getResourceLoader() {
return resourceLoader;
}
public void setResourceLoader(Supplier resourceLoader) {
this.resourceLoader = Objects.requireNonNull(resourceLoader);
}
public Collection getRootPackageList() {
return scanner.getRootPackages();
}
public interface AbstractBeanFactory {
Object createBean(String beanName, BeanDefinition definition, Object[] args) throws RuntimeException;
}
public interface Aware {
}
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
public interface ApplicationAware extends Aware {
void setApplication(ApplicationX applicationX);
}
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
void destroy() throws Exception;
}
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) throws RuntimeException {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) throws RuntimeException {
return bean;
}
}
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
default void postProcessMergedBeanDefinition(BeanDefinition beanDefinition, Class> beanType, String beanName) {
}
default void resetBeanDefinition(String beanName) {
}
}
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
default Class> predictBeanType(Class> beanClass, String beanName) throws RuntimeException {
return null;
}
default Constructor>[] determineCandidateConstructors(Class> beanClass, String beanName)
throws RuntimeException {
return null;
}
}
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
default Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws RuntimeException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws RuntimeException {
return true;
}
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws RuntimeException {
return pvs;
}
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws RuntimeException {
return pvs;
}
}
public interface ConversionService {
default boolean canConvert(Class> sourceType, Class> targetType) {
return true;
}
default T convert(Object source, Class targetType) {
return (T) source;
}
}
public interface PropertyEditor {
/**
* Gets the property value.
*
* @return The value of the property. Primitive types such as "int" will
* be wrapped as the corresponding object type such as "java.lang.Integer".
*/
Object getValue();
/**
* Set (or change) the object that is to be edited. Primitive types such
* as "int" must be wrapped as the corresponding object type such as
* "java.lang.Integer".
*
* @param value The new target object to be edited. Note that this
* object should not be modified by the PropertyEditor, rather
* the PropertyEditor should create a new object to hold any
* modified value.
*/
void setValue(Object value);
}
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
/**
* The name of this bean, or if several names, a primary bean name plus aliases.
* If left unspecified, the name of the bean is the name of the annotated method.
* If specified, the method name is ignored.
*
* @return String[]
*/
String[] value() default {};
}
@Target(TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
String value() default "";
}
@Target({CONSTRUCTOR, METHOD, PARAMETER, FIELD, ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
// TODO: 1月27日 027 @Value not impl config
@Target({CONSTRUCTOR, METHOD, PARAMETER, FIELD, ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
String value() default "";
}
@Target({TYPE, METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {
}
@Target({CONSTRUCTOR, METHOD, PARAMETER, FIELD, ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Resource {
String name() default "";
Class> type() default Object.class;
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}
@Target({TYPE, METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
String value() default BeanDefinition.SCOPE_SINGLETON;
}
@Target({TYPE, METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Lazy {
boolean value() default true;
}
@Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {
/**
* 从小到大排列
*
* @return 排序
*/
int value() default Integer.MAX_VALUE;
}
public interface Ordered {
/**
* 从小到大排列
*
* @return 排序
*/
int getOrder();
}
/**
* 1.扫描class文件
* 2.创建对象并包装
*/
public static class Scanner {
private final Collection rootPackages = new ArrayList<>(6);
private final Collection excludes = new LinkedHashSet<>(6);
public Collection getRootPackages() {
return rootPackages;
}
public Collection getExcludes() {
return this.excludes;
}
public void doScan(String basePackage, String currentPackage, URL url, BiConsumer classConsumer) throws IOException {
StringBuilder buffer = new StringBuilder();
String splashPath = dotToSplash(basePackage);
if (url == null || existContains(url)) {
return;
}
String filePath = getRootPath(URLDecoder.decode(url.getFile(), "UTF-8"));
List names;
if (isJarFile(filePath)) {
names = readFromJarFile(filePath, splashPath);
} else {
names = readFromDirectory(filePath);
}
for (String name : names) {
if (isClassFile(name)) {
String className = toClassName(buffer, name, currentPackage);
classConsumer.accept(url, className);
} else {
String nextPackage;
if (currentPackage == null || currentPackage.isEmpty()) {
nextPackage = name;
} else {
nextPackage = currentPackage + "." + name;
}
doScan(basePackage, nextPackage, new URL(url + "/" + name), classConsumer);
}
}
}
public void doScan(String basePackage, ClassLoader loader, BiConsumer classConsumer) throws IOException {
StringBuilder buffer = new StringBuilder();
String splashPath = dotToSplash(basePackage);
URL url = loader.getResource(splashPath);
if (url == null || existContains(url)) {
return;
}
String filePath = getRootPath(url.getFile());
List names;
if (isJarFile(filePath)) {
names = readFromJarFile(filePath, splashPath);
} else {
names = readFromDirectory(filePath);
}
for (String name : names) {
if (isClassFile(name)) {
String className = toClassName(buffer, name, basePackage);
classConsumer.accept(url, className);
} else {
doScan(basePackage + "." + name, loader, classConsumer);
}
}
}
private boolean existContains(URL url) {
if (excludes.isEmpty()) {
return false;
}
String[] urlStr = url.getPath().split("/");
for (String s : excludes) {
for (String u : urlStr) {
if (u.equals(s)) {
return true;
}
}
}
return false;
}
private String toClassName(StringBuilder buffer, String shortName, String basePackage) {
buffer.setLength(0);
shortName = trimExtension(shortName);
if (shortName.contains(basePackage)) {
buffer.append(shortName);
} else {
buffer.append(basePackage).append('.').append(shortName);
}
return buffer.toString();
}
// if(jarPath.equals("/git/api/erp.jar"))
// jarPath = "git/api/erp.jar";
private List readFromJarFile(String jarPath, String splashedPackageName) throws IOException {
JarInputStream jarIn = new JarInputStream(new FileInputStream(jarPath));
JarEntry entry = jarIn.getNextJarEntry();
List nameList = new ArrayList<>();
while (null != entry) {
String name = entry.getName();
if (!entry.isDirectory() && name.startsWith(splashedPackageName) && isClassFile(name)) {
nameList.add(name);
}
entry = jarIn.getNextJarEntry();
}
return nameList;
}
private List readFromDirectory(String path) {
File file = new File(path);
String[] names = file.list();
if (null == names) {
return Collections.emptyList();
}
return Arrays.asList(names);
}
private boolean isClassFile(String name) {
return name.endsWith(".class");
}
private boolean isJarFile(String name) {
return name.endsWith(".jar");
}
private String getRootPath(String fileUrl) {
int pos = fileUrl.indexOf('!');
if (-1 == pos) {
return fileUrl;
}
return fileUrl.substring(5, pos);
}
/**
* "cn.fh.lightning" -> "cn/fh/lightning"
*/
private String dotToSplash(String name) {
return name.replaceAll("\\.", "/");
}
/**
* "com/git/Apple.class" -> "com.git.Apple"
*/
private String trimExtension(String name) {
int pos = name.indexOf('.');
if (-1 != pos) {
name = name.substring(0, pos);
}
return name.replace("/", ".");
}
/**
* /application/home -> /home
*/
private String trimURI(String uri) {
String trimmed = uri.substring(1);
int splashIndex = trimmed.indexOf('/');
return trimmed.substring(splashIndex);
}
@Override
public String toString() {
return "Scanner{" +
"rootPackages=" + rootPackages +
", excludes=" + excludes +
'}';
}
}
/**
* 参考 org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement
*
* @param 成员
*/
public static class InjectElement {
private static final String[] QUALIFIER_FIELDS = new String[]{"value", "name"};
/**
* 成员有[构造器,方法,字段] {@link Constructor,Method,Field}
*/
private final T member;
/**
* 用于获取注入参数
*/
private final ApplicationX applicationX;
/**
* 自动注入标记的注解
*/
private final Annotation autowiredAnnotation;
/**
* 注入类型如下 {@link BeanDefinition#AUTOWIRE_BY_NAME,BeanDefinition#AUTOWIRE_BY_TYPE}
*/
private final int[] autowireType;
/**
* 这个参数是否是必须的 (会覆盖这些参数是否是必须的)
*/
private final Boolean[] requireds;
/**
* 这个包含泛型注入的类型
*/
private Type[] requiredType;
/**
* 这个如果是泛型注入,则Class会是Object, 所以需要requiredType
*/
private Class[] requiredClass;
/**
* 如果根据名称注入
*/
private String[] requiredName;
/**
* 这些参数是否是必须的
*/
private Boolean required;
public InjectElement(Executable executable, ApplicationX applicationX) {
int parameterCount = executable.getParameterCount();
this.member = (T) executable;
this.applicationX = applicationX;
this.autowiredAnnotation = findDeclaredAnnotation(executable, applicationX.autowiredAnnotations, AUTOWIRED_ANNOTATION_CACHE_MAP);
this.autowireType = new int[parameterCount];
this.requiredClass = new Class[parameterCount];
this.requiredType = new Type[parameterCount];
this.requiredName = new String[parameterCount];
this.requireds = new Boolean[parameterCount];
Parameter[] parameters = executable.getParameters();
for (int i = 0; i < parameterCount; i++) {
Parameter parameter = parameters[i];
this.requiredClass[i] = parameter.getType();
this.autowireType[i] = applicationX.findAutowireType(parameter);
switch (this.autowireType[i]) {
default:
case BeanDefinition.AUTOWIRE_BY_TYPE: {
Annotation parameterInjectAnnotation = findDeclaredAnnotation(parameter, applicationX.autowiredAnnotations, AUTOWIRED_ANNOTATION_CACHE_MAP);
this.requiredType[i] = findAnnotationDeclaredType(parameterInjectAnnotation, parameter.getParameterizedType());
Annotation qualifierAnnotation = findDeclaredAnnotation(parameter, applicationX.qualifierAnnotations, QUALIFIER_ANNOTATION_CACHE_MAP);
String autowiredBeanName = qualifierAnnotation != null ?
getQualifierAnnotationValue(qualifierAnnotation) : null;
this.requiredName[i] = autowiredBeanName;
break;
}
case BeanDefinition.AUTOWIRE_BY_NAME: {
Annotation qualifierAnnotation = findDeclaredAnnotation(parameter, applicationX.qualifierAnnotations, QUALIFIER_ANNOTATION_CACHE_MAP);
String autowiredBeanName = qualifierAnnotation != null ?
getQualifierAnnotationValue(qualifierAnnotation) : parameter.getName();
this.requiredName[i] = autowiredBeanName;
break;
}
}
Annotation parameterAutowiredAnnotation = findDeclaredAnnotation(parameter, applicationX.autowiredAnnotations, AUTOWIRED_ANNOTATION_CACHE_MAP);
this.requireds[i] = parameterAutowiredAnnotation != null ?
getAnnotationValue(parameterAutowiredAnnotation, "required", Boolean.class) : null;
}
if (this.autowiredAnnotation != null) {
this.required = getAnnotationValue(this.autowiredAnnotation, "required", Boolean.class);
}
}
public InjectElement(Field field, ApplicationX applicationX) {
this.member = (T) field;
this.applicationX = applicationX;
this.autowiredAnnotation = findDeclaredAnnotation(field, applicationX.autowiredAnnotations, AUTOWIRED_ANNOTATION_CACHE_MAP);
this.autowireType = new int[]{applicationX.findAutowireType(field)};
this.requiredClass = new Class[]{field.getType()};
switch (this.autowireType[0]) {
default:
case BeanDefinition.AUTOWIRE_BY_TYPE: {
this.requiredType = new Type[]{findAnnotationDeclaredType(this.autowiredAnnotation, field.getGenericType())};
}
case BeanDefinition.AUTOWIRE_BY_NAME: {
Annotation qualifierAnnotation = findDeclaredAnnotation(field, applicationX.qualifierAnnotations, QUALIFIER_ANNOTATION_CACHE_MAP);
String autowiredBeanName = qualifierAnnotation != null ?
getQualifierAnnotationValue(qualifierAnnotation) : field.getName();
this.requiredName = new String[]{autowiredBeanName};
break;
}
}
if (this.autowiredAnnotation != null) {
this.required = getAnnotationValue(this.autowiredAnnotation, "required", Boolean.class);
}
this.requireds = new Boolean[]{this.required};
}
private static String getQualifierAnnotationValue(Annotation qualifierAnnotation) {
return getAnnotationValue(qualifierAnnotation, QUALIFIER_FIELDS, String.class);
}
public static List> getInjectFields(Class rootClass, ApplicationX applicationX) {
List> list = new ArrayList<>();
for (Class clazz = rootClass; clazz != null && clazz != Object.class; clazz = clazz.getSuperclass()) {
for (Field field : clazz.getDeclaredFields()) {
//寻找打着注解的字段
if (null != findDeclaredAnnotation(field, applicationX.autowiredAnnotations, AUTOWIRED_ANNOTATION_CACHE_MAP)) {
InjectElement element = new InjectElement<>(field, applicationX);
list.add(element);
}
}
}
return list;
}
public static List> getInjectMethods(Class rootClass, ApplicationX applicationX) {
List> result = new ArrayList<>();
eachClass(rootClass, clazz -> {
for (Method method : getDeclaredMethods(clazz)) {
//寻找打着注解的方法
if (null != findDeclaredAnnotation(method, applicationX.autowiredAnnotations, AUTOWIRED_ANNOTATION_CACHE_MAP)) {
result.add(new InjectElement<>(method, applicationX));
}
}
});
return result;
}
private static Class findConcreteClass(Class> parameterGenericClass, Class concreteChildClass) {
BiFunction, Class>> findFunction = (generic, genericSuper) -> {
if (generic instanceof ParameterizedType) {
for (Type actualTypeArgument : ((ParameterizedType) generic).getActualTypeArguments()) {
if (actualTypeArgument instanceof Class
&& genericSuper.isAssignableFrom((Class>) actualTypeArgument)) {
return (Class) actualTypeArgument;
}
}
}
return null;
};
Class> result = findFunction.apply(concreteChildClass.getGenericSuperclass(), parameterGenericClass);
if (result == null) {
for (Type genericInterface : concreteChildClass.getGenericInterfaces()) {
if (null != (result = findFunction.apply(genericInterface, parameterGenericClass))) {
break;
}
}
}
return result == null ? parameterGenericClass : result;
}
private static Type findAnnotationDeclaredType(Annotation annotation, Type def) {
if (annotation == null) {
return def;
}
Type annotationDeclaredType = getAnnotationValue(annotation, "type", Type.class);
if (annotationDeclaredType != null && annotationDeclaredType != Object.class) {
return annotationDeclaredType;
} else {
return def;
}
}
/**
* 会根据类型或名称调用getBean()方法, 返回需要的所有参数. {@link BeanDefinition#AUTOWIRE_BY_TYPE,BeanDefinition#AUTOWIRE_BY_NAME}
*
* @param targetClass 注入目标类
* @return 从容器中取出的多个bean
* @throws IllegalStateException 如果容器中不存在需要的bean
*/
private Object[] getInjectValues(Class targetClass) throws IllegalStateException {
Boolean defaultRequired = this.required;
if (defaultRequired == null) {
defaultRequired = Boolean.FALSE;
}
Object[] values = new Object[autowireType.length];
for (int i = 0; i < autowireType.length; i++) {
Object injectResource = null;
Boolean required = requireds[i];
if (required == null) {
required = defaultRequired;
}
Object desc;
switch (autowireType[i]) {
case BeanDefinition.AUTOWIRE_BY_NAME: {
desc = requiredName[i];
injectResource = applicationX.getBean(requiredName[i], null, false);
break;
}
case BeanDefinition.AUTOWIRE_BY_TYPE:
default: {
Class> autowireClass = requiredType[i] instanceof Class ?
(Class) requiredType[i] : findConcreteClass(requiredClass[i], targetClass);
desc = autowireClass;
if (requiredName[i] != null) {
Object byName = applicationX.getBean(requiredName[i], null, false);
if (byName != null && autowireClass.isAssignableFrom(byName.getClass())) {
injectResource = byName;
}
}
if (injectResource == null) {
if (autowireClass == Object.class) {
injectResource = null;
} else if (isAbstract(autowireClass)) {
List implList = applicationX.getBeanForType(autowireClass);
int size = implList.size();
if (size == 0) {
injectResource = null;
} else if (size == 1) {
injectResource = implList.get(0);
} else {
injectResource = applicationX.getBean(autowireClass, null, false);
}
} else {
injectResource = applicationX.getBean(autowireClass, null, false);
}
}
break;
}
}
if (injectResource == null && required) {
throw new IllegalStateException("Required part[" + (i + 1) + "] '" + desc + "' is not present. member='" + member + "',class=" + member.getDeclaringClass() + ". Dependency annotations: Autowired(required=false)");
}
values[i] = injectResource;
}
return values;
}
/**
* 注入
*
* @param target 需要注入的实例
* @param targetClass 需要注入的原始类型,用于查找泛型
* @return 如果是方法, 则返回方法返回值. 如果是构造器,返回实例. 如果是字段返回null
* @throws IllegalStateException 注入异常
*/
public Object inject(Object target, Class targetClass) throws IllegalStateException {
if (targetClass == null) {
targetClass = target.getClass();
}
if (this.member instanceof Field) {
Field field = (Field) this.member;
if (Modifier.isFinal(field.getModifiers())) {
return null;
}
//获取注入的参数
Object[] values = getInjectValues(targetClass);
try {
boolean accessible = field.isAccessible();
try {
//调用java的字段赋值, 相当于this.field = value
field.setAccessible(true);
field.set(target, values[0]);
} finally {
field.setAccessible(accessible);
}
} catch (Throwable e) {
throw new IllegalStateException("inject error=" + e + ". class=" + target.getClass() + ",field=" + this.member);
}
} else if (this.member instanceof Method) {
Method method = (Method) this.member;
Object[] values = getInjectValues(targetClass);
try {
boolean accessible = method.isAccessible();
try {
//调用java的字段赋值, 相当于setValue(values)
method.setAccessible(true);
return method.invoke(target, values);
} finally {
method.setAccessible(accessible);
}
} catch (Throwable e) {
throw new IllegalStateException("inject error=" + e + ". class=" + target.getClass() + ",method=" + this.member);
}
} else if (this.member instanceof Constructor) {
return newInstance(null);
}
return null;
}
public Object newInstance(Object[] args) throws IllegalStateException {
//不能创建枚举类
if (this.member.getDeclaringClass().isEnum()) {
return null;
}
if (!(this.member instanceof Constructor)) {
throw new IllegalStateException("member not instanceof Constructor!");
}
Constructor constructor = (Constructor) this.member;
//如果用户在getBean(name,args)没有传参数
if (args == null || args.length == 0) {
//获取注入的参数
args = getInjectValues(member.getDeclaringClass());
}
boolean accessible = constructor.isAccessible();
try {
//相当于 new MyBean(args)
constructor.setAccessible(true);
Object instance = constructor.newInstance(args);
return instance;
} catch (IllegalAccessException | InstantiationException |
InvocationTargetException | IllegalArgumentException |
ExceptionInInitializerError e) {
throw new IllegalStateException("inject error=" + e + ". method=" + this.member, e);
} finally {
constructor.setAccessible(accessible);
}
}
}
private static class DefaultBeanNameGenerator implements Function {
private final Map scannerAnnotationCacheMap = newConcurrentReferenceMap(32);
private final ApplicationX applicationX;
public DefaultBeanNameGenerator(ApplicationX applicationX) {
this.applicationX = Objects.requireNonNull(applicationX);
}
@Override
public String apply(BeanDefinition definition) {
Class beanClass = definition.getBeanClassIfResolve(applicationX.resourceLoader);
Annotation annotation = findDeclaredAnnotation(beanClass, applicationX.scannerAnnotations, scannerAnnotationCacheMap);
String beanName = null;
if (annotation != null) {
beanName = getAnnotationValue(annotation, "value", String.class);
}
if (beanName == null || beanName.isEmpty()) {
String className = beanClass.getName();
int lastDotIndex = className.lastIndexOf('.');
int nameEndIndex = className.indexOf("$$");
if (nameEndIndex == -1) {
nameEndIndex = className.length();
}
String shortName = className.substring(lastDotIndex + 1, nameEndIndex);
shortName = shortName.replace('$', '.');
beanName = Introspector.decapitalize(shortName);
}
return beanName;
}
}
public static class BeanDefinition {
public static final String SCOPE_SINGLETON = "singleton";
public static final String SCOPE_PROTOTYPE = "prototype";
public static final int AUTOWIRE_NO = 0;
public static final int AUTOWIRE_BY_NAME = 1;
public static final int AUTOWIRE_BY_TYPE = 2;
public static final int AUTOWIRE_CONSTRUCTOR = 3;
public static final int DEPENDENCY_CHECK_NONE = 0;
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
public static final int DEPENDENCY_CHECK_ALL = 3;
final Object postProcessingLock = new Object();
private final Map attributes = new LinkedHashMap<>();
private final Map constructorArgumentValues = new LinkedHashMap<>();
private boolean postProcessed = false;
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
private Supplier> beanSupplier;
private Object beanClass;
private String beanClassName;
private String scope = SCOPE_SINGLETON;
private boolean primary = false;
private boolean lazyInit = false;
private String initMethodName;
private String destroyMethodName;
private int autowireMode = AUTOWIRE_NO;
private PropertyValues propertyValues = PropertyValues.EMPTY;
private boolean allowCaching = true;
//用于aop等代理对象
private volatile Boolean beforeInstantiationResolved;
public BeanDefinition() {
}
public Map getConstructorArgumentValues() {
return constructorArgumentValues;
}
public String getDestroyMethodName() {
return destroyMethodName;
}
public void setDestroyMethodName(String destroyMethodName) {
this.destroyMethodName = destroyMethodName;
}
public int getDependencyCheck() {
return dependencyCheck;
}
public void setDependencyCheck(int dependencyCheck) {
this.dependencyCheck = dependencyCheck;
}
public String getInitMethodName() {
return initMethodName;
}
public void setInitMethodName(String initMethodName) {
this.initMethodName = initMethodName;
}
public boolean isSingleton() {
return SCOPE_SINGLETON.equals(scope);
}
public boolean isPrototype() {
return SCOPE_PROTOTYPE.equals(scope);
}
public boolean isLazyInit() {
return lazyInit;
}
public void setLazyInit(boolean lazyInit) {
this.lazyInit = lazyInit;
}
public boolean isPrimary() {
return primary;
}
public void setPrimary(boolean primary) {
this.primary = primary;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public PropertyValues getPropertyValues() {
return this.propertyValues;
}
public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
public Boolean getBeforeInstantiationResolved() {
return beforeInstantiationResolved;
}
public void setBeforeInstantiationResolved(Boolean beforeInstantiationResolved) {
this.beforeInstantiationResolved = beforeInstantiationResolved;
}
public Class getBeanClass() {
if (beanClass == null) {
throw new IllegalStateException("No bean class specified on bean definition");
}
if (!(beanClass instanceof Class)) {
throw new IllegalStateException(
"Bean class name [" + beanClass + "] has not been resolved into an actual Class");
}
return (Class) beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public Class getBeanClassIfResolve(Supplier loaderSupplier) {
if (beanClass == null || !(beanClass instanceof Class)) {
beanClass = resolveBeanClass(loaderSupplier.get());
}
return (Class) beanClass;
}
public Class resolveBeanClass(ClassLoader classLoader) {
try {
return Class.forName(beanClassName, false, classLoader);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("getBeanClass error." + e, e);
}
}
public Supplier> getBeanSupplier() {
return beanSupplier;
}
public void setBeanSupplier(Supplier> beanSupplier) {
this.beanSupplier = beanSupplier;
}
public void setAttribute(String name, Object value) {
attributes.put(name, value);
}
public Object removeAttribute(String name) {
return attributes.remove(name);
}
public Object getAttribute(String name) {
return attributes.get(name);
}
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
}
public int getAutowireMode() {
return this.autowireMode;
}
public void setAutowireMode(int autowireMode) {
this.autowireMode = autowireMode;
}
@Override
public String toString() {
return scope + '{' + beanClassName + '}';
}
}
public static class ValueHolder {
private Object value;
private String type;
private String name;
private Object source;
private boolean converted = false;
private Object convertedValue;
public ValueHolder(Object value) {
this.value = value;
}
}
public static class PropertyValues implements Iterable {
public static PropertyValues EMPTY = new PropertyValues(new PropertyValue[0]);
private PropertyValue[] propertyValues;
public PropertyValues(PropertyValue[] propertyValues) {
this.propertyValues = propertyValues;
}
@Override
public Iterator iterator() {
return Arrays.asList(getPropertyValues()).iterator();
}
@Override
public Spliterator spliterator() {
return Spliterators.spliterator(getPropertyValues(), 0);
}
public Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
public PropertyValue[] getPropertyValues() {
return propertyValues;
}
public boolean contains(String propertyName) {
for (PropertyValue value : propertyValues) {
if (Objects.equals(propertyName, value.name)) {
return true;
}
}
return false;
}
public boolean isEmpty() {
return propertyValues.length == 0;
}
}
/*==============static-utils=============================*/
public static class PropertyValue {
private final Map attributes = new LinkedHashMap<>();
private final String name;
private final Object value;
private Object source;
private boolean optional = false;
private boolean converted = false;
private Object convertedValue;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
}
public static class OrderComparator implements Comparator