shz.spring.BeanContainer Maven / Gradle / Ivy
package shz.spring;
import com.alibaba.fastjson2.JSON;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AopProxy;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import shz.core.*;
import shz.core.cl.ClassLoaderHelp;
import shz.core.constant.ArrayConstant;
import shz.core.constant.NullConstant;
import shz.core.msg.ClientFailureMsg;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.*;
import java.util.regex.Pattern;
/**
* 执行顺序
* //@AutoConfigureAfter:在指定的配置类初始化后再加载
* //@AutoConfigureBefore:在指定的配置类初始化前加载
* //@AutoConfigureOrder:数越小越先初始化
*
* 条件配置
* //@ConditionalOnClass : classpath中存在该类时起效
* //@ConditionalOnMissingClass : classpath中不存在该类时起效
* //@ConditionalOnBean : DI容器中存在该类型Bean时起效
* //@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
* //@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
* //@ConditionalOnExpression : SpEL表达式结果为true时
* //@ConditionalOnProperty : 参数设置或者值一致时起效
* //@ConditionalOnResource : 指定的文件存在时起效
* //@ConditionalOnJndi : 指定的JNDI存在时起效
* //@ConditionalOnJava : 指定的Java版本存在时起效
* //@ConditionalOnWebApplication : Web应用环境下起效
* //@ConditionalOnNotWebApplication : 非Web应用环境下起效
*/
@SuppressWarnings("unchecked")
public final class BeanContainer implements ApplicationContextInitializer, BeanDefinitionRegistryPostProcessor, Ordered {
private static volatile ApplicationContext context;
private static Environment environment;
private static volatile DefaultListableBeanFactory beanFactory;
private static final Object setMonitor = new Object();
/**
* 执行列表
*/
private static List TODO_LIST = new CopyOnWriteArrayList<>();
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
if (context != null) return;
synchronized (setMonitor) {
if (context != null) return;
context = applicationContext;
environment = context.getEnvironment();
if (beanFactory != null) {
TODO_LIST.stream().sorted(Comparator.comparing(Todo::order)).forEach(Todo::execute);
TODO_LIST = null;
}
}
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
if (beanFactory != null || !(configurableListableBeanFactory instanceof DefaultListableBeanFactory)) return;
synchronized (setMonitor) {
if (beanFactory != null) return;
beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
if (context != null) {
TODO_LIST.stream().sorted(Comparator.comparing(Todo::order)).forEach(Todo::execute);
TODO_LIST = null;
}
}
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
public static ApplicationContext getContext() {
return context;
}
public static Environment getEnvironment() {
return environment;
}
public static DefaultListableBeanFactory getBeanFactory() {
return beanFactory;
}
public static T get(String name) {
T bean = null;
try {
bean = (T) context.getBean(name);
} catch (Throwable ignored) {
}
return bean;
}
public static void set(int order, Runnable setter) {
if (context == null || beanFactory == null) {
synchronized (setMonitor) {
if (context == null || beanFactory == null) {
TODO_LIST.add(new Todo() {
@Override
public int order() {
return order;
}
@Override
public void execute() {
setter.run();
}
});
return;
}
}
}
setter.run();
}
public static void set(Runnable setter) {
set(0, setter);
}
public static void set(int order, String name, Consumer setter) {
set(order, () -> setter.accept(get(name)));
}
public static void set(String name, Consumer setter) {
set(0, name, setter);
}
public static T get(String name, Supplier supplier) {
T bean = get(name);
if (bean != null) return bean;
if (supplier == null) return null;
bean = supplier.get();
if (bean != null) try {
beanFactory.registerSingleton(name, bean);
} catch (Throwable ignored) {
}
return bean;
}
public static void set(int order, String name, Supplier supplier, Consumer setter) {
set(order, () -> setter.accept(get(name, supplier)));
}
public static void set(String name, Supplier supplier, Consumer setter) {
set(0, name, supplier, setter);
}
public static T get(Class extends T> cls) {
T bean = null;
try {
bean = context.getBean(cls);
} catch (Throwable ignored) {
}
return bean;
}
public static void set(int order, Class extends T> cls, Consumer setter) {
set(order, () -> setter.accept(get(cls)));
}
public static void set(Class extends T> cls, Consumer setter) {
set(0, cls, setter);
}
public static T get(Class extends T> cls, Supplier supplier) {
T bean = get(cls);
if (bean != null) return bean;
if (supplier == null) return null;
bean = supplier.get();
if (bean != null) try {
beanFactory.registerSingleton(cls.toGenericString(), bean);
} catch (Throwable ignored) {
}
return bean;
}
public static void set(int order, Class extends T> cls, Supplier supplier, Consumer setter) {
set(order, () -> setter.accept(get(cls, supplier)));
}
public static void set(Class extends T> cls, Supplier supplier, Consumer setter) {
set(0, cls, supplier, setter);
}
public static T get(String name, String className) {
T bean = get(name);
if (bean != null) return bean;
Class cls = (Class) ClassLoaderHelp.load(className, true, ClassLoaderHelp.get());
if (cls == null) return null;
return get(cls, () -> AccessibleHelp.newInstance(cls));
}
public static void set(int order, String name, String className, Consumer setter) {
set(order, () -> setter.accept(get(name, className)));
}
public static void set(String name, String className, Consumer setter) {
set(0, name, className, setter);
}
public static Class getBeanClass(Object bean) {
return (Class) (AopUtils.isAopProxy(bean) ? AopUtils.getTargetClass(bean) : bean.getClass());
}
public static T getTargetBean(Object bean) {
while (true) if (!AopUtils.isAopProxy(bean = getTargetBean0(bean))) break;
return (T) bean;
}
private static Object getTargetBean0(Object bean) {
try {
if (AopUtils.isJdkDynamicProxy(bean)) return getJdkTargetBean(bean);
else if (AopUtils.isCglibProxy(bean)) return getCglibTargetBean(bean);
} catch (Exception e) {
return null;
}
return bean;
}
private static Object getJdkTargetBean(Object proxy) throws Exception {
Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
h.setAccessible(true);
AopProxy aopProxy = (AopProxy) h.get(proxy);
Field advised = aopProxy.getClass().getDeclaredField("advised");
advised.setAccessible(true);
return ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();
}
private static Object getCglibTargetBean(Object proxy) throws Exception {
Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
h.setAccessible(true);
Object dynamicAdvisedInterceptor = h.get(proxy);
Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
advised.setAccessible(true);
return ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
}
private static final DefaultParameterNameDiscoverer PND = new DefaultParameterNameDiscoverer();
public static String[] getParameterNames(Method method) {
return PND.getParameterNames(method);
}
public static String[] getParameterNames(Constructor> constructor) {
return PND.getParameterNames(constructor);
}
public static void registerBeanDefinition(int order, Class> cls, Class> fbCls, Object... args) {
set(order, () -> registerBeanDefinition0(cls, fbCls, args));
}
private static void registerBeanDefinition0(Class> cls, Class> fbCls, Object... args) {
if (context.containsBeanDefinition(cls.getSimpleName())) return;
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(cls);
GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
ConstructorArgumentValues argumentValues = definition.getConstructorArgumentValues();
for (int i = 0; i < args.length; ++i) argumentValues.addIndexedArgumentValue(i, args[i]);
definition.setBeanClass(fbCls);
definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
beanFactory.registerBeanDefinition(cls.getSimpleName(), definition);
}
public static void registerBeanDefinition(Class> cls, Class> fbCls, Object... args) {
registerBeanDefinition(0, cls, fbCls, args);
}
public static void registerBeanDefinitionAnnotatedWith(int order, Class aCls, Class> fbCls, Function, Object[]> func) {
set(order, () -> AccessibleHelp.consumerClasses(c -> {
if (c.isAnnotationPresent(aCls)) registerBeanDefinition0(c, fbCls, func.apply(c));
return 0;
}, 0));
}
public static void registerBeanDefinitionAnnotatedWith(Class aCls, Class> fbCls, Function, Object[]> func) {
registerBeanDefinitionAnnotatedWith(0, aCls, fbCls, func);
}
public static void registerBeanDefinitionChildes(int order, Class> cls, Class> fbCls, Function, Object[]> func) {
set(order, () -> AccessibleHelp.consumerClasses(c -> {
if (cls.isAssignableFrom(c)) registerBeanDefinition0(c, fbCls, func.apply(c));
return 0;
}, 0));
}
public static void registerBeanDefinitionChildes(Class> cls, Class> fbCls, Function, Object[]> func) {
registerBeanDefinitionChildes(0, cls, fbCls, func);
}
public static Pattern API_PATTERN = Pattern.compile("\\$\\{[^{}]+?}");
public static String getExpressionProperty(String s) {
if (NullHelp.isBlank(s)) return s;
String s0;
while (!s.equals(s0 = getExpressionProperty0(s))) s = s0;
return s;
}
private static String getExpressionProperty0(String s) {
return RegexHelp.replace(s, API_PATTERN, matcher -> {
String expression = matcher.group(0);
int idx = expression.indexOf(':');
if (idx == -1) return environment.getProperty(expression.substring(2, expression.length() - 1));
String key = expression.substring(2, idx);
String value = environment.getProperty(key);
if (NullHelp.nonBlank(value) || environment.containsProperty(key)) return value;
return environment.getProperty(expression.substring(idx + 1, expression.length() - 1));
});
}
public static void setExpressionProperty(int order, String s, Consumer setter) {
set(order, () -> setter.accept(getExpressionProperty(s)));
}
public static void setExpressionProperty(String s, Consumer setter) {
setExpressionProperty(0, s, setter);
}
public static String getProperty(String key) {
return environment.getProperty(key);
}
public static void setProperty(int order, String key, Consumer setter) {
set(order, () -> setter.accept(getProperty(key)));
}
public static void setProperty(String key, Consumer setter) {
setProperty(0, key, setter);
}
public static void consumerBeanAnnotatedWith(int order, Class cls, BiConsumer beanConsumer) {
set(order, () -> context.getBeansWithAnnotation(cls).forEach(beanConsumer));
}
public static void consumerBeanAnnotatedWith(Class cls, BiConsumer beanConsumer) {
consumerBeanAnnotatedWith(0, cls, beanConsumer);
}
public static void consumerBean(int order, Predicate beanNamePredicate, Predicate