All Downloads are FREE. Search and download functionalities are using the official Maven repository.

vip.justlive.oxygen.ioc.IocPlugin Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2020 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 vip.justlive.oxygen.ioc;

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import vip.justlive.oxygen.core.Plugin;
import vip.justlive.oxygen.core.config.ConfigFactory;
import vip.justlive.oxygen.core.exception.Exceptions;
import vip.justlive.oxygen.core.scan.ClassScannerPlugin;
import vip.justlive.oxygen.core.util.ClassUtils;
import vip.justlive.oxygen.core.util.ServiceLoaderUtils;
import vip.justlive.oxygen.ioc.annotation.Bean;
import vip.justlive.oxygen.ioc.annotation.Inject;
import vip.justlive.oxygen.ioc.annotation.Named;
import vip.justlive.oxygen.ioc.store.BeanProxy;
import vip.justlive.oxygen.ioc.store.BeanStore;
import vip.justlive.oxygen.ioc.store.DefaultBeanProxy;
import vip.justlive.oxygen.ioc.store.DefaultBeanStore;

/**
 * IocPlugin
 * 
* 当前只支持构造方法注入 *
* 原因: 易于切换不同ioc实现 * * @author wubo */ @Slf4j public class IocPlugin implements Plugin { private static final BeanStore BEAN_STORE = new DefaultBeanStore(); private static final BeanProxy BEAN_PROXY; static { List list = ServiceLoaderUtils.loadServices(BeanProxy.class); if (list.isEmpty()) { BEAN_PROXY = new DefaultBeanProxy(); } else { Collections.sort(list); BEAN_PROXY = list.get(0); } } /** * 获取beanStore * * @return beanStore */ public static BeanStore beanStore() { return BEAN_STORE; } /** * 获取beanProxy * * @return beanProxy */ public static BeanProxy beanProxy() { return BEAN_PROXY; } @Override public int order() { return Integer.MIN_VALUE + 10; } @Override public void start() { ioc(); } @Override public void stop() { BEAN_STORE.clean(); } private void ioc() { Set> beanClasses = ClassScannerPlugin.getTypesAnnotatedWith(Bean.class); Map, ClassInfo> iocMap = new HashMap<>(8); for (Class clazz : beanClasses) { Bean bean; if (clazz.isInterface() || (bean = ClassUtils.getAnnotation(clazz, Bean.class)) == null) { continue; } String beanName = bean.value(); if (beanName.length() == 0) { beanName = clazz.getName(); } tryInstance(clazz, beanName, bean.order(), iocMap); } int count = iocMap.size(); while (count > 0) { reIoc(iocMap); if (count == iocMap.size()) { if (log.isDebugEnabled()) { log.debug("ioc失败 出现循环依赖或缺失Bean fail-ioc-map {}", iocMap); } throw Exceptions.fail("发生循环依赖或者缺失Bean "); } count = iocMap.size(); } } /** * try instance * * @param clazz 类 * @param beanName name of bean * @param order order of bean * @return instance successful if true */ private static boolean tryInstance(Class clazz, String beanName, int order) { Constructor constructor = getConstructor(clazz); if (constructor != null) { Object bean = dependencyInstance(clazz, constructor); if (bean == null) { return false; } ConfigFactory.load(bean); BEAN_STORE.addBean(beanName, bean, order); return true; } Object bean = BEAN_PROXY.proxy(clazz); ConfigFactory.load(bean); BEAN_STORE.addBean(beanName, bean, order); return true; } private void tryInstance(Class clazz, String beanName, int order, Map, ClassInfo> iocMap) { if (!tryInstance(clazz, beanName, order)) { iocMap.put(clazz, new ClassInfo(beanName, getConstructor(clazz), order)); } } private static Constructor getConstructor(Class clazz) { Constructor[] constructors = clazz.getConstructors(); Constructor constructor; if (constructors.length == 1) { constructor = constructors[0]; } else { constructor = ClassUtils.getConstructorAnnotatedWith(constructors, Inject.class); } return constructor; } private static Object dependencyInstance(Class clazz, Constructor constructor) { Parameter[] params = constructor.getParameters(); Object[] args = new Object[params.length]; for (int i = 0; i < params.length; i++) { if (params[i].isAnnotationPresent(Named.class)) { args[i] = BEAN_STORE.getBean(params[i].getAnnotation(Named.class).value()); } else { args[i] = BEAN_STORE.getBean(params[i].getType()); } if (args[i] == null) { return null; } } return BEAN_PROXY.proxy(clazz, args); } private void reIoc(Map, ClassInfo> iocMap) { Iterator, ClassInfo>> it = iocMap.entrySet().iterator(); while (it.hasNext()) { Entry, ClassInfo> entry = it.next(); ClassInfo classInfo = entry.getValue(); Object bean = dependencyInstance(entry.getKey(), classInfo.constructor); if (bean != null) { ConfigFactory.load(bean); BEAN_STORE.addBean(classInfo.name, bean, classInfo.order); it.remove(); } } } private static class ClassInfo { final String name; final Constructor constructor; final int order; ClassInfo(String name, Constructor constructor, int order) { this.name = name; this.constructor = constructor; this.order = order; } @Override public String toString() { return String.format("[name=%s, %s]", name, constructor); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy