bean容器重构ing.
This commit is contained in:
@@ -35,5 +35,5 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Lazy {
|
||||
|
||||
boolean value() default true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,419 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import fun.asgc.neutrino.core.context.LifeCycle;
|
||||
import fun.asgc.neutrino.core.context.LifeCycleManager;
|
||||
import fun.asgc.neutrino.core.context.LifeCycleStatus;
|
||||
import fun.asgc.neutrino.core.exception.BeanException;
|
||||
import fun.asgc.neutrino.core.util.Assert;
|
||||
import fun.asgc.neutrino.core.util.CollectionUtil;
|
||||
import fun.asgc.neutrino.core.util.LockUtil;
|
||||
import fun.asgc.neutrino.core.util.TypeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 抽象的bean工厂
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/1
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, LifeCycle {
|
||||
/**
|
||||
* 父工厂
|
||||
*/
|
||||
private AbstractBeanFactory parent;
|
||||
/**
|
||||
* bean缓存
|
||||
*/
|
||||
protected Map<BeanIdentity, BeanWrapper> beanCache;
|
||||
/**
|
||||
* 互斥锁
|
||||
*/
|
||||
private Object mutex;
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 生命周期管理
|
||||
*/
|
||||
private LifeCycleManager lifeCycleManager = LifeCycleManager.create();
|
||||
|
||||
public AbstractBeanFactory(String name) {
|
||||
this(null, name);
|
||||
}
|
||||
|
||||
public AbstractBeanFactory(AbstractBeanFactory parent, String name) {
|
||||
Assert.notNull(name, "工厂名称不能为空");
|
||||
this.parent = parent;
|
||||
this.beanCache = new ConcurrentHashMap<>(256);
|
||||
this.name = name;
|
||||
if (null == parent) {
|
||||
this.mutex = new Object();
|
||||
} else {
|
||||
this.mutex = parent.getMutex();
|
||||
}
|
||||
this.registerBean(this, this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getBean(String name, Object... args) throws BeanException {
|
||||
Assert.notEmpty(name, "Bean名称不能为空!");
|
||||
T bean = (null == parent) ? null : parent.getBean(name, args);
|
||||
return null != bean ? bean : doGetBean(name, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getBean(Class<T> type, Object... args) throws BeanException {
|
||||
Assert.notNull(type, "Bean类型不能为空!");
|
||||
T bean = (null == parent) ? null : parent.getBean(type, args);
|
||||
return null != bean ? bean : doGetBean(type, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getBeanByTypeAndName(Class<T> type, String name, Object... args) throws BeanException {
|
||||
Assert.notEmpty(name, "Bean名称不能为空!");
|
||||
Assert.notNull(type, "Bean类型不能为空!");
|
||||
T bean = (null == parent) ? null : parent.getBeanByTypeAndName(type, name, args);
|
||||
return null != bean ? bean : doGetBeanByNameAndType(name, type, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getBean(BeanIdentity identity, Object... args) throws BeanException {
|
||||
Assert.notNull(identity, "Bean的身份标识不能为空!");
|
||||
return (T)getBeanByTypeAndName(identity.getType(), identity.getName(), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> getBeanList(Class<T> type, Object... args) throws BeanException {
|
||||
return CollectionUtil.addAll(() -> new LinkedList<>(),
|
||||
null == parent ? null : parent.getBeanList(type, args),
|
||||
doGetBeanList(type, args)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBean(Class<?> type, String name) {
|
||||
boolean res = (null != parent) ? parent.hasBean(type, name) : false;
|
||||
return res || doHasBean(type, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countBean(String name) {
|
||||
int count = (null != parent) ? parent.countBean(name) : 0;
|
||||
return count + doCountBean(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countBean(Class<?> type) {
|
||||
int count = (null != parent) ? parent.countBean(type) : 0;
|
||||
return count + doCountBean(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBean(Object obj) throws BeanException {
|
||||
Assert.notNull(obj, "被注册的bean实例不能为空!");
|
||||
String name = TypeUtil.getDefaultVariableName(obj.getClass());
|
||||
registerBean(obj, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动new出来的bean注册进来,视为已经初始化了
|
||||
* @param obj
|
||||
* @param name
|
||||
* @throws BeanException
|
||||
*/
|
||||
@Override
|
||||
public void registerBean(Object obj, String name) throws BeanException {
|
||||
Assert.notNull(obj, "被注册的bean实例不能为空!");
|
||||
Assert.notNull(obj, "被注册的bean名称不能为空!");
|
||||
synchronized (mutex) {
|
||||
if (hasBean(obj.getClass(), name)) {
|
||||
throw new BeanException(String.format("Bean[type:%s name:%s] 已存在,不能重复注册!", obj.getClass().getName(), name));
|
||||
}
|
||||
addBean(new BeanWrapper()
|
||||
.setType(obj.getClass())
|
||||
.setName(name)
|
||||
.setInstance(obj)
|
||||
.setStatus(BeanStatus.INIT)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBean(Class<?> type) throws BeanException {
|
||||
registerBean(type, TypeUtil.getDefaultVariableName(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBean(Class<?> type, String name) throws BeanException {
|
||||
synchronized (mutex) {
|
||||
if (hasBean(type, name)) {
|
||||
throw new BeanException(String.format("Bean[type:%s name:%s] 已存在,不能重复注册!", type.getName(), name));
|
||||
}
|
||||
addBean(type, name);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T doGetBean(String name, Object... args) throws BeanException {
|
||||
List<BeanWrapper> beanList = findBeanList(name);
|
||||
if (CollectionUtil.isEmpty(beanList)) {
|
||||
return null;
|
||||
} else if (beanList.size() > 1) {
|
||||
throw new BeanException(String.format("Bean[name:%s] 存在多个实例!", name));
|
||||
}
|
||||
return getOrNew(beanList.get(0));
|
||||
}
|
||||
|
||||
private <T> T doGetBean(Class<T> type, Object... args) throws BeanException {
|
||||
List<BeanWrapper> beanList = findBeanList(type);
|
||||
if (CollectionUtil.isEmpty(beanList)) {
|
||||
return null;
|
||||
} else if (beanList.size() > 1) {
|
||||
throw new BeanException(String.format("Bean[type:%s] 存在多个实例!", type));
|
||||
}
|
||||
return getOrNew(beanList.get(0));
|
||||
}
|
||||
|
||||
private <T> T doGetBeanByNameAndType(String name, Class<T> type, Object... args) throws BeanException {
|
||||
BeanWrapper bean = findBean(type, name);
|
||||
if (null == bean) {
|
||||
return null;
|
||||
}
|
||||
return getOrNew(bean);
|
||||
}
|
||||
|
||||
private <T> List<T> doGetBeanList(Class<T> type, Object... args) throws BeanException {
|
||||
List<BeanWrapper> beanList = findBeanList(type);
|
||||
if (CollectionUtil.isEmpty(beanList)) {
|
||||
return null;
|
||||
}
|
||||
return getOrNew(beanList);
|
||||
}
|
||||
|
||||
private boolean doHasBean(Class<?> type, String name) {
|
||||
return beanCache.containsKey(new BeanIdentity(name, type));
|
||||
}
|
||||
|
||||
private int doCountBean(String name) {
|
||||
return beanCache.keySet().stream().filter(e -> e.getName().equals(name)).collect(Collectors.counting()).intValue();
|
||||
}
|
||||
|
||||
private int doCountBean(Class<?> type) {
|
||||
return beanCache.keySet().stream().filter(e -> type.isAssignableFrom(e.getType())).collect(Collectors.counting()).intValue();
|
||||
}
|
||||
|
||||
public Object getMutex() {
|
||||
return mutex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找bean
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
private List<BeanWrapper> findBeanList(String name) {
|
||||
Assert.notNull(name, "bean的名称不能为空!");
|
||||
List<BeanWrapper> beanList = new LinkedList<>();
|
||||
for (BeanIdentity identity : beanCache.keySet()) {
|
||||
if (identity.getName().equals(name)) {
|
||||
beanList.add(beanCache.get(identity));
|
||||
}
|
||||
}
|
||||
return beanList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找bean
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private List<BeanWrapper> findBeanList(Class<?> type) {
|
||||
Assert.notNull(type, "bean的类型不能为空!");
|
||||
List<BeanWrapper> beanList = new LinkedList<>();
|
||||
for (BeanIdentity identity : beanCache.keySet()) {
|
||||
if (type.isAssignableFrom(identity.getType())) {
|
||||
beanList.add(beanCache.get(identity));
|
||||
}
|
||||
}
|
||||
return beanList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找bean
|
||||
* @param type
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
private BeanWrapper findBean(Class<?> type, String name) {
|
||||
Assert.notNull(type, "bean的类型不能为空!");
|
||||
Assert.notNull(name, "bean的名称不能为空!");
|
||||
return beanCache.get(new BeanIdentity(name, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增一个bean
|
||||
* @param bean
|
||||
*/
|
||||
protected void addBean(BeanWrapper bean) {
|
||||
beanCache.put(new BeanIdentity(bean.getName(), bean.getType()), bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
lifeCycleManager.init(() -> {
|
||||
if (null != parent) {
|
||||
parent.init();
|
||||
}
|
||||
if (CollectionUtil.notEmpty(beanCache)) {
|
||||
beanCache.values().stream().filter(b -> BeanStatus.INJECT == b.getStatus()).forEach(bean -> bean.init());
|
||||
}
|
||||
log.info("bean工厂[{}]初始化.", getName());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
lifeCycleManager.destroy(() -> {
|
||||
if (null != parent) {
|
||||
parent.destroy();
|
||||
}
|
||||
if (CollectionUtil.notEmpty(beanCache)) {
|
||||
beanCache.values().stream().filter(b -> BeanStatus.DESTROY != b.getStatus()).forEach(bean -> bean.destroy());
|
||||
}
|
||||
log.info("bean工厂[{}]销毁.", getName());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取或创建实例
|
||||
* @param beanList
|
||||
* @param <T>
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
protected <T> List<T> getOrNew(List<BeanWrapper> beanList) throws BeanException {
|
||||
List<T> list = new LinkedList<>();
|
||||
if (CollectionUtil.isEmpty(beanList)) {
|
||||
return list;
|
||||
}
|
||||
for (BeanWrapper bean : beanList) {
|
||||
T instance = getOrNew(bean);
|
||||
if (null == instance) {
|
||||
throw new BeanException(String.format("Bean[type:%s name:%s]实例化失败!", bean.getType().getName(), bean.getName()));
|
||||
}
|
||||
list.add(instance);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取名称
|
||||
* @return
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取生命周期状态
|
||||
* @return
|
||||
*/
|
||||
public LifeCycleStatus getLifeCycleStatus() {
|
||||
return lifeCycleManager.getStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取生命周期管理对象
|
||||
* @return
|
||||
*/
|
||||
public LifeCycleManager getLifeCycleManager() {
|
||||
return lifeCycleManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增一个bean
|
||||
* @param type
|
||||
* @param name
|
||||
*/
|
||||
protected abstract void addBean(Class<?> type, String name);
|
||||
|
||||
/**
|
||||
* 获取或创建实例
|
||||
* @param bean
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
protected <T> T getOrNew(BeanWrapper bean) throws BeanException {
|
||||
return (T)LockUtil.doubleCheckProcess(
|
||||
() -> !(BeanStatus.INIT == bean.getStatus() || BeanStatus.RUNNING == bean.getStatus()),
|
||||
bean,
|
||||
() -> {
|
||||
if (BeanStatus.REGISTER == bean.getStatus()) {
|
||||
dependencyCheck(bean);
|
||||
}
|
||||
if (BeanStatus.DEPENDENCY_CHECKING == bean.getStatus()) {
|
||||
newInstance(bean);
|
||||
}
|
||||
if (BeanStatus.INSTANCE == bean.getStatus()) {
|
||||
inject(bean);
|
||||
}
|
||||
if (BeanStatus.INJECT == bean.getStatus()) {
|
||||
bean.init();
|
||||
}
|
||||
},
|
||||
() -> bean.getInstance()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 依赖关系检测
|
||||
* @param bean
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
protected abstract boolean dependencyCheck(BeanWrapper bean) throws BeanException;
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
* @param bean
|
||||
* @param <T>
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
protected abstract <T> T newInstance(BeanWrapper bean) throws BeanException;
|
||||
|
||||
/**
|
||||
* 注入
|
||||
* @param bean
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
protected abstract boolean inject(BeanWrapper bean) throws BeanException;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import fun.asgc.neutrino.core.exception.BeanException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/1
|
||||
*/
|
||||
public interface BeanFactory {
|
||||
|
||||
/**
|
||||
* 尝试根据名称获取bean
|
||||
* @param name
|
||||
* @param args
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
<T> T getBean(String name, Object... args) throws BeanException;
|
||||
|
||||
/**
|
||||
* 尝试根据类型获取bean
|
||||
* @param type
|
||||
* @param args
|
||||
* @param <T>
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
<T> T getBean(Class<T> type, Object... args) throws BeanException;
|
||||
|
||||
/**
|
||||
* 尝试根据Bean身份标识获取bean
|
||||
* @param identity
|
||||
* @param args
|
||||
* @param <T>
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
<T> T getBean(BeanIdentity identity, Object... args) throws BeanException;
|
||||
|
||||
/**
|
||||
* 根据类型+名称获取bean
|
||||
* @param type
|
||||
* @param name
|
||||
* @param args
|
||||
* @param <T>
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
<T> T getBeanByTypeAndName(Class<T> type, String name, Object... args) throws BeanException;
|
||||
|
||||
/**
|
||||
* 尝试根据类型获取bean
|
||||
* @param type
|
||||
* @param args
|
||||
* @param <T>
|
||||
* @return
|
||||
* @throws BeanException
|
||||
*/
|
||||
<T> List<T> getBeanList(Class<T> type, Object... args) throws BeanException;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import fun.asgc.neutrino.core.util.Assert;
|
||||
|
||||
/**
|
||||
* 用于标识bean的身份
|
||||
*
|
||||
* 此处用名称+类型作为bean的唯一标识
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/1
|
||||
*/
|
||||
public class BeanIdentity implements Identity {
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private Class<?> type;
|
||||
/**
|
||||
* hashCode
|
||||
*/
|
||||
private int identityHashCode;
|
||||
|
||||
public BeanIdentity(String name, Class<?> type) {
|
||||
Assert.notEmpty(name, "名称不能为空!");
|
||||
Assert.notNull(type, "类型不能为空!");
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.identityHashCode = System.identityHashCode(name) + System.identityHashCode(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取名称
|
||||
* @return
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型
|
||||
* @return
|
||||
*/
|
||||
public Class<?> getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnly() {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (null == obj) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof BeanIdentity)) {
|
||||
return false;
|
||||
}
|
||||
BeanIdentity beanIdentity = (BeanIdentity)obj;
|
||||
return this.name.equals(beanIdentity.getName()) && this.type.equals(beanIdentity.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return identityHashCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import fun.asgc.neutrino.core.exception.BeanException;
|
||||
|
||||
/**
|
||||
* bean注册表
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/1
|
||||
*/
|
||||
public interface BeanRegistry {
|
||||
|
||||
/**
|
||||
* 注册bean
|
||||
* @param obj
|
||||
* @throws BeanException
|
||||
*/
|
||||
void registerBean(Object obj) throws BeanException;
|
||||
|
||||
/**
|
||||
* 注册bean
|
||||
* @param obj
|
||||
* @param name
|
||||
* @throws BeanException
|
||||
*/
|
||||
void registerBean(Object obj, String name) throws BeanException;
|
||||
|
||||
/**
|
||||
* 注册bean
|
||||
* @param type
|
||||
* @throws BeanException
|
||||
*/
|
||||
void registerBean(Class<?> type) throws BeanException;
|
||||
|
||||
/**
|
||||
* 注册bean
|
||||
* @param type
|
||||
* @param name
|
||||
* @throws BeanException
|
||||
*/
|
||||
void registerBean(Class<?> type, String name) throws BeanException;
|
||||
|
||||
/**
|
||||
* 判断是否包含此bean
|
||||
* @param type
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
boolean hasBean(Class<?> type, String name);
|
||||
|
||||
/**
|
||||
* 查询bean容器中有多少个叫该名称的bean
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
int countBean(String name);
|
||||
|
||||
/**
|
||||
* 查询bean容器中有多少个该类型的bean
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
int countBean(Class<?> type);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Bean的几种状态
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/2
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum BeanStatus {
|
||||
REGISTER(1, "已注册"),
|
||||
DEPENDENCY_CHECKING(2, "依赖关系检测完成"),
|
||||
INSTANCE(3, "已实例化"),
|
||||
INJECT(4, "已完成注入"),
|
||||
INIT(5, "已初始化"),
|
||||
RUNNING(6, "运行中"),
|
||||
DESTROY(7, "已销毁");
|
||||
private static final Map<Integer, BeanStatus> cache = Stream.of(BeanStatus.values()).collect(Collectors.toMap(BeanStatus::getStatus, Function.identity()));
|
||||
|
||||
private Integer status;
|
||||
private String desc;
|
||||
|
||||
public static BeanStatus of(Integer status) {
|
||||
return cache.get(status);
|
||||
}
|
||||
}
|
||||
+32
-25
@@ -20,22 +20,23 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package fun.asgc.neutrino.core.context;
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import fun.asgc.neutrino.core.annotation.*;
|
||||
import fun.asgc.neutrino.core.aop.Aop;
|
||||
import fun.asgc.neutrino.core.container.LifeCycle;
|
||||
import fun.asgc.neutrino.core.context.LifeCycle;
|
||||
import fun.asgc.neutrino.core.container.BeanContainer;
|
||||
import fun.asgc.neutrino.core.context.ApplicationConfig;
|
||||
import fun.asgc.neutrino.core.context.ApplicationContext;
|
||||
import fun.asgc.neutrino.core.context.Environment;
|
||||
import fun.asgc.neutrino.core.util.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -45,14 +46,16 @@ import java.util.stream.Stream;
|
||||
@Slf4j
|
||||
@Accessors(chain = true)
|
||||
@Data
|
||||
public class Bean implements LifeCycle {
|
||||
public class BeanWrapper implements LifeCycle {
|
||||
private String name;
|
||||
private Class<?> clazz;
|
||||
private Class<?> type;
|
||||
private Object instance;
|
||||
private Component component;
|
||||
private int order;
|
||||
private boolean isBoot;
|
||||
private volatile boolean isInit;
|
||||
private BeanStatus status;
|
||||
private boolean isLazy;
|
||||
|
||||
public boolean hasInstance() {
|
||||
return null != instance;
|
||||
@@ -68,14 +71,14 @@ public class Bean implements LifeCycle {
|
||||
}
|
||||
isInit = true;
|
||||
|
||||
Set<Method> methods = ReflectUtil.getMethods(clazz);
|
||||
Set<Method> methods = ReflectUtil.getMethods(type);
|
||||
if (CollectionUtil.notEmpty(methods)) {
|
||||
for (Method method : methods) {
|
||||
if (method.isAnnotationPresent(Init.class) && method.getParameters().length == 0) {
|
||||
try {
|
||||
method.invoke(instance);
|
||||
} catch (Exception e) {
|
||||
log.error(String.format("初始化方法执行异常 class:%s method:%s", clazz.getName(), method.getName()), e);
|
||||
log.error(String.format("初始化方法执行异常 class:%s method:%s", type.getName(), method.getName()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,14 +90,14 @@ public class Bean implements LifeCycle {
|
||||
if (!hasInstance()) {
|
||||
return;
|
||||
}
|
||||
Set<Method> methods = ReflectUtil.getMethods(clazz);
|
||||
Set<Method> methods = ReflectUtil.getMethods(type);
|
||||
if (CollectionUtil.notEmpty(methods)) {
|
||||
for (Method method : methods) {
|
||||
if (method.isAnnotationPresent(Destroy.class) && method.getParameters().length == 0) {
|
||||
try {
|
||||
method.invoke(instance);
|
||||
} catch (Exception e) {
|
||||
log.error(String.format("销毁方法执行异常 class:%s method:%s", clazz.getName(), method.getName()), e);
|
||||
log.error(String.format("销毁方法执行异常 class:%s method:%s", type.getName(), method.getName()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,14 +119,14 @@ public class Bean implements LifeCycle {
|
||||
() -> {
|
||||
try {
|
||||
// 暂时先只支持yml配置
|
||||
Configuration configuration = clazz.getAnnotation(Configuration.class);
|
||||
Configuration configuration = type.getAnnotation(Configuration.class);
|
||||
if (null != configuration) {
|
||||
instance = ConfigUtil.getYmlConfig(clazz);
|
||||
} else if (ClassUtil.isInterface(clazz)) {
|
||||
instance = Aop.get(clazz);
|
||||
instance = ConfigUtil.getYmlConfig(type);
|
||||
} else if (ClassUtil.isInterface(type)) {
|
||||
instance = Aop.get(type);
|
||||
} else {
|
||||
// 由编码规避没有无参构造器的问题
|
||||
instance = clazz.newInstance();
|
||||
instance = type.newInstance();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
@@ -134,7 +137,7 @@ public class Bean implements LifeCycle {
|
||||
}
|
||||
|
||||
private void inject(ApplicationContext context) {
|
||||
Set<Method> methods = ReflectUtil.getMethods(clazz);
|
||||
Set<Method> methods = ReflectUtil.getMethods(type);
|
||||
if (CollectionUtil.notEmpty(methods)) {
|
||||
methods.stream().forEach(method -> {
|
||||
fun.asgc.neutrino.core.annotation.Bean bean = method.getAnnotation(fun.asgc.neutrino.core.annotation.Bean.class);
|
||||
@@ -153,8 +156,8 @@ public class Bean implements LifeCycle {
|
||||
log.error("bean 实例不能为空!");
|
||||
return;
|
||||
}
|
||||
context.getBeanContainer().addBean(new Bean()
|
||||
.setClazz(obj.getClass())
|
||||
context.getBeanContainer().addBean(new BeanWrapper()
|
||||
.setType(obj.getClass())
|
||||
.setBoot(false)
|
||||
.setComponent(null)
|
||||
.setInstance(obj)
|
||||
@@ -167,7 +170,7 @@ public class Bean implements LifeCycle {
|
||||
}
|
||||
});
|
||||
}
|
||||
Set<Field> fieldSet = ReflectUtil.getInheritChainDeclaredFieldSet(clazz);
|
||||
Set<Field> fieldSet = ReflectUtil.getInheritChainDeclaredFieldSet(type);
|
||||
if (CollectionUtil.notEmpty(fieldSet)) {
|
||||
fieldSet.forEach(field -> {
|
||||
Autowired autowired = field.getAnnotation(Autowired.class);
|
||||
@@ -184,17 +187,17 @@ public class Bean implements LifeCycle {
|
||||
ReflectUtil.setFieldValue(field, instance, context);
|
||||
} else {
|
||||
Class<?> autowiredType = field.getType();
|
||||
Bean autowiredBean = null;
|
||||
BeanWrapper autowiredBean = null;
|
||||
if (StringUtil.isEmpty(autowired.value())) {
|
||||
autowiredBean = context.getBeanContainer().getBean(autowiredType);
|
||||
} else {
|
||||
autowiredBean = context.getBeanContainer().getBean(autowired.value());
|
||||
}
|
||||
if (null == autowiredBean) {
|
||||
throw new RuntimeException(String.format("类 %s 自动装配字段:%s 依赖bean不存在!", clazz.getName(), field.getName()));
|
||||
throw new RuntimeException(String.format("类 %s 自动装配字段:%s 依赖bean不存在!", type.getName(), field.getName()));
|
||||
}
|
||||
if (autowiredBean.isDependOn(clazz)) {
|
||||
throw new RuntimeException(String.format("类[%s]与类[%s]存在循环依赖!", clazz.getName(), field.getType().getName()));
|
||||
if (autowiredBean.isDependOn(type)) {
|
||||
throw new RuntimeException(String.format("类[%s]与类[%s]存在循环依赖!", type.getName(), field.getType().getName()));
|
||||
}
|
||||
autowiredBean.newInstance(context);
|
||||
ReflectUtil.setFieldValue(field, instance, autowiredBean.getInstance());
|
||||
@@ -204,7 +207,7 @@ public class Bean implements LifeCycle {
|
||||
}
|
||||
|
||||
public boolean isLazy() {
|
||||
Lazy lazy = ClassUtil.getAnnotation(clazz, Lazy.class);
|
||||
Lazy lazy = ClassUtil.getAnnotation(type, Lazy.class);
|
||||
return null != lazy;
|
||||
}
|
||||
|
||||
@@ -212,7 +215,7 @@ public class Bean implements LifeCycle {
|
||||
if (null == target) {
|
||||
return false;
|
||||
}
|
||||
Set<Field> fieldSet = ReflectUtil.getInheritChainDeclaredFieldSet(clazz);
|
||||
Set<Field> fieldSet = ReflectUtil.getInheritChainDeclaredFieldSet(type);
|
||||
if (CollectionUtil.isEmpty(fieldSet)) {
|
||||
return false;
|
||||
}
|
||||
@@ -227,4 +230,8 @@ public class Bean implements LifeCycle {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/2
|
||||
*/
|
||||
public class ClassScanner {
|
||||
private Set<Class<?>> classes = new HashSet<>();
|
||||
private List<String> scanBasePackages;
|
||||
|
||||
public ClassScanner(List<String> scanBasePackages) {
|
||||
this.scanBasePackages = scanBasePackages;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
/**
|
||||
* Identity 用于标识一个身份。
|
||||
*
|
||||
* 当`isOnly()`为true时,该标识是一个唯一标识。
|
||||
*
|
||||
* 如:身份证、财富、年龄都可以作为人的身份象征,但只有身份证是唯一标识。
|
||||
* 这个唯一性取决与理论上的定义,而非实际数据。
|
||||
* 例如有三个人,年龄分别是18、19、20,此时对于这三人而言,年龄是唯一的,但年龄这个标识我们仍然认为是非唯一标识。
|
||||
* 除非在特定场景下,这些数据固定不变、或者确保以后新增的数据也不会打破这一设定。
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/1
|
||||
*/
|
||||
public interface Identity {
|
||||
/**
|
||||
* 是否唯一标识
|
||||
* @return
|
||||
*/
|
||||
boolean isOnly();
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import fun.asgc.neutrino.core.annotation.Lazy;
|
||||
import fun.asgc.neutrino.core.annotation.Order;
|
||||
import fun.asgc.neutrino.core.exception.BeanException;
|
||||
import fun.asgc.neutrino.core.runner.ApplicationRunner;
|
||||
import fun.asgc.neutrino.core.util.ClassUtil;
|
||||
import fun.asgc.neutrino.core.util.CollectionUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: 一个简单的bean工厂实现
|
||||
* @date: 2022/7/2
|
||||
*/
|
||||
@Slf4j
|
||||
public class SimpleBeanFactory extends AbstractBeanFactory {
|
||||
|
||||
public SimpleBeanFactory(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public SimpleBeanFactory(AbstractBeanFactory parent, String name) {
|
||||
super(parent, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addBean(Class<?> type, String name) {
|
||||
log.debug("addBean[type:{} name:{}]", type.getName(), name);
|
||||
BeanWrapper beanWrapper = new BeanWrapper()
|
||||
.setType(type)
|
||||
.setName(name)
|
||||
.setLazy(Boolean.FALSE)
|
||||
.setOrder(Integer.MAX_VALUE)
|
||||
.setStatus(BeanStatus.REGISTER);
|
||||
Lazy lazy = ClassUtil.getAnnotation(type, Lazy.class);
|
||||
if (null != lazy) {
|
||||
beanWrapper.setLazy(lazy.value());
|
||||
}
|
||||
Order order = ClassUtil.getAnnotation(type, Order.class);
|
||||
if (null != order) {
|
||||
beanWrapper.setOrder(order.value());
|
||||
}
|
||||
addBean(beanWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean dependencyCheck(BeanWrapper bean) throws BeanException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> T newInstance(BeanWrapper bean) throws BeanException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean inject(BeanWrapper bean) throws BeanException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
List<BeanWrapper> beanWrapperList = beanCache.values().stream()
|
||||
.filter(b -> b.getStatus().getStatus() < BeanStatus.INIT.getStatus())
|
||||
.filter(b -> ApplicationRunner.class.isAssignableFrom(b.getType()) || !b.isLazy() || b.getOrder() <= 0)
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtil.notEmpty(beanWrapperList)) {
|
||||
getOrNew(beanWrapperList);
|
||||
}
|
||||
super.init();
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,4 @@ package fun.asgc.neutrino.core.container;
|
||||
*/
|
||||
public interface ApplicationContainer extends Container {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
package fun.asgc.neutrino.core.container;
|
||||
|
||||
import fun.asgc.neutrino.core.context.Bean;
|
||||
import fun.asgc.neutrino.core.bean.BeanWrapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -52,24 +52,24 @@ public interface BeanContainer extends Container {
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
Bean getBean(Class<?> clazz);
|
||||
BeanWrapper getBean(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* 获取bean实例
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
Bean getBean(String name);
|
||||
BeanWrapper getBean(String name);
|
||||
|
||||
/**
|
||||
* 获取bean集合
|
||||
* @return
|
||||
*/
|
||||
List<Bean> beanList();
|
||||
List<BeanWrapper> beanList();
|
||||
|
||||
/**
|
||||
* 添加bean
|
||||
* @param bean
|
||||
*/
|
||||
void addBean(Bean bean);
|
||||
void addBean(BeanWrapper bean);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
package fun.asgc.neutrino.core.container;
|
||||
|
||||
import fun.asgc.neutrino.core.context.LifeCycle;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class DefaultApplicationContainer implements ApplicationContainer {
|
||||
this.beanContainer.beanList().forEach(bean -> {
|
||||
if (bean.isBoot()) {
|
||||
if (bean.hasInstance()) {
|
||||
if (ApplicationRunner.class.isAssignableFrom(bean.getClazz())) {
|
||||
if (ApplicationRunner.class.isAssignableFrom(bean.getType())) {
|
||||
ApplicationRunner runner = (ApplicationRunner)bean.getInstance();
|
||||
runner.run(environment.getMainArgs());
|
||||
}
|
||||
|
||||
+13
-13
@@ -25,7 +25,7 @@ package fun.asgc.neutrino.core.container;
|
||||
import com.google.common.collect.Lists;
|
||||
import fun.asgc.neutrino.core.annotation.Component;
|
||||
import fun.asgc.neutrino.core.annotation.Order;
|
||||
import fun.asgc.neutrino.core.context.Bean;
|
||||
import fun.asgc.neutrino.core.bean.BeanWrapper;
|
||||
import fun.asgc.neutrino.core.cache.Cache;
|
||||
import fun.asgc.neutrino.core.cache.MemoryCache;
|
||||
import fun.asgc.neutrino.core.context.Environment;
|
||||
@@ -49,9 +49,9 @@ import java.util.List;
|
||||
public class DefaultBeanContainer implements BeanContainer {
|
||||
private Environment environment;
|
||||
private ClassContainer classContainer;
|
||||
private Cache<String, Bean> nameBeanCache;
|
||||
private Cache<Class<?>, Bean> classBeanCache;
|
||||
private List<Bean> beans;
|
||||
private Cache<String, BeanWrapper> nameBeanCache;
|
||||
private Cache<Class<?>, BeanWrapper> classBeanCache;
|
||||
private List<BeanWrapper> beans;
|
||||
|
||||
public DefaultBeanContainer(Environment environment) {
|
||||
this.environment = environment;
|
||||
@@ -72,12 +72,12 @@ public class DefaultBeanContainer implements BeanContainer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bean getBean(Class<?> clazz) {
|
||||
public BeanWrapper getBean(Class<?> clazz) {
|
||||
return classBeanCache.get(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bean getBean(String name) {
|
||||
public BeanWrapper getBean(String name) {
|
||||
return nameBeanCache.get(name);
|
||||
}
|
||||
|
||||
@@ -96,8 +96,8 @@ public class DefaultBeanContainer implements BeanContainer {
|
||||
orderValue = order.value();
|
||||
}
|
||||
|
||||
addBean(new Bean()
|
||||
.setClazz(clazz)
|
||||
addBean(new BeanWrapper()
|
||||
.setType(clazz)
|
||||
.setName(name)
|
||||
.setComponent(component)
|
||||
.setOrder(orderValue)
|
||||
@@ -107,7 +107,7 @@ public class DefaultBeanContainer implements BeanContainer {
|
||||
|
||||
if (!classBeanCache.isEmpty()) {
|
||||
beans = Lists.newArrayList(classBeanCache.values());
|
||||
Collections.sort(beans, Comparator.comparingInt(Bean::getOrder));
|
||||
Collections.sort(beans, Comparator.comparingInt(BeanWrapper::getOrder));
|
||||
}
|
||||
|
||||
log.info("bean容器初始化完成");
|
||||
@@ -120,21 +120,21 @@ public class DefaultBeanContainer implements BeanContainer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBean(Bean bean) {
|
||||
public void addBean(BeanWrapper bean) {
|
||||
if (null == bean) {
|
||||
return;
|
||||
}
|
||||
// TODO 暂时由编码时规避名字冲突
|
||||
if (ApplicationRunner.class.isAssignableFrom(bean.getClazz())) {
|
||||
if (ApplicationRunner.class.isAssignableFrom(bean.getType())) {
|
||||
bean.setOrder(Integer.MIN_VALUE);
|
||||
bean.setBoot(true);
|
||||
}
|
||||
classBeanCache.set(bean.getClazz(), bean);
|
||||
classBeanCache.set(bean.getType(), bean);
|
||||
nameBeanCache.set(bean.getName(), bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Bean> beanList() {
|
||||
public List<BeanWrapper> beanList() {
|
||||
return beans;
|
||||
}
|
||||
}
|
||||
|
||||
+103
-2
@@ -22,10 +22,22 @@
|
||||
|
||||
package fun.asgc.neutrino.core.context;
|
||||
|
||||
import fun.asgc.neutrino.core.annotation.Component;
|
||||
import fun.asgc.neutrino.core.aop.interceptor.ExceptionHandler;
|
||||
import fun.asgc.neutrino.core.aop.interceptor.Filter;
|
||||
import fun.asgc.neutrino.core.aop.interceptor.Interceptor;
|
||||
import fun.asgc.neutrino.core.aop.interceptor.ResultAdvice;
|
||||
import fun.asgc.neutrino.core.bean.SimpleBeanFactory;
|
||||
import fun.asgc.neutrino.core.container.BeanContainer;
|
||||
import fun.asgc.neutrino.core.util.StringUtil;
|
||||
import fun.asgc.neutrino.core.runner.ApplicationRunner;
|
||||
import fun.asgc.neutrino.core.util.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -34,7 +46,8 @@ import lombok.experimental.Accessors;
|
||||
*/
|
||||
@Accessors(chain = true)
|
||||
@Data
|
||||
public class ApplicationContext {
|
||||
@Slf4j
|
||||
public class ApplicationContext implements LifeCycle {
|
||||
|
||||
/**
|
||||
* 应用环境
|
||||
@@ -48,4 +61,92 @@ public class ApplicationContext {
|
||||
* bean容器
|
||||
*/
|
||||
private BeanContainer beanContainer;
|
||||
/**
|
||||
* 根Bean工厂
|
||||
*/
|
||||
private SimpleBeanFactory rootBeanFactory;
|
||||
/**
|
||||
* bean工厂
|
||||
*/
|
||||
private SimpleBeanFactory applicationBeanFactory;
|
||||
/**
|
||||
* 生命周期管理者
|
||||
*/
|
||||
private LifeCycleManager lifeCycleManager = LifeCycleManager.create();
|
||||
|
||||
public ApplicationContext() {
|
||||
|
||||
}
|
||||
|
||||
public ApplicationContext(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void init() {
|
||||
this.lifeCycleManager.init(() -> {
|
||||
try {
|
||||
this.rootBeanFactory = new SimpleBeanFactory("rootBeanFactory");
|
||||
this.applicationBeanFactory = new SimpleBeanFactory(rootBeanFactory, "applicationBeanFactory");
|
||||
this.rootBeanFactory.registerBean(environment, "rootEnvironment");
|
||||
this.rootBeanFactory.registerBean(this, "rootApplicationContext");
|
||||
this.rootBeanFactory.registerBean(environment.getConfig(), "rootApplicationConfig");
|
||||
register();
|
||||
this.applicationBeanFactory.init();
|
||||
// TODO 后面优化掉这种不安全的BeanManager
|
||||
BeanManager.setContext(this);
|
||||
} catch (Exception e) {
|
||||
log.error("应用上下文初始化异常!", e);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
log.info("应用上下文初始化完成");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.lifeCycleManager.destroy(() -> {
|
||||
|
||||
this.applicationBeanFactory.destroy();
|
||||
log.info("应用上下文销毁");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* bean注册
|
||||
* 所有的拦截器默认都是bean组件,没带Component注解时,默认是延迟加载的
|
||||
*/
|
||||
private void register() throws IOException, ClassNotFoundException {
|
||||
Set<Class<?>> classes = ClassUtil.scan(environment.getScanBasePackages());
|
||||
if (CollectionUtil.isEmpty(classes)) {
|
||||
return;
|
||||
}
|
||||
classes.stream()
|
||||
.filter(item -> ClassUtil.isAnnotateWith(item, Component.class)
|
||||
|| Interceptor.class.isAssignableFrom(item)
|
||||
|| Filter.class.isAssignableFrom(item)
|
||||
|| ExceptionHandler.class.isAssignableFrom(item)
|
||||
|| ResultAdvice.class.isAssignableFrom(item)
|
||||
)
|
||||
.forEach(clazz -> {
|
||||
String beanName = TypeUtil.getDefaultVariableName(clazz);
|
||||
Component component = ClassUtil.getAnnotation(clazz, Component.class);
|
||||
if (null != component && StringUtil.notEmpty(component.value())) {
|
||||
beanName = component.value();
|
||||
}
|
||||
this.applicationBeanFactory.registerBean(clazz, beanName);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用上下文启动
|
||||
*/
|
||||
public void run() {
|
||||
init();
|
||||
List<ApplicationRunner> applicationRunnerList = this.applicationBeanFactory.getBeanList(ApplicationRunner.class);
|
||||
if (CollectionUtil.notEmpty(applicationRunnerList)) {
|
||||
applicationRunnerList.forEach(applicationRunner -> applicationRunner.run(this.environment.getMainArgs()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package fun.asgc.neutrino.core.container;
|
||||
package fun.asgc.neutrino.core.context;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.context;
|
||||
|
||||
import fun.asgc.neutrino.core.base.CodeBlock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: 生命周期管理
|
||||
* @date: 2022/7/2
|
||||
*/
|
||||
public class LifeCycleManager {
|
||||
/**
|
||||
* 生命周期状态
|
||||
*/
|
||||
private LifeCycleStatus status;
|
||||
|
||||
private LifeCycleManager() {
|
||||
this.status = LifeCycleStatus.CREATE;
|
||||
}
|
||||
|
||||
public synchronized void init(CodeBlock codeBlock) {
|
||||
if (this.status == LifeCycleStatus.CREATE) {
|
||||
codeBlock.execute();
|
||||
this.status = LifeCycleStatus.INIT;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void run(CodeBlock codeBlock) {
|
||||
if (this.status == LifeCycleStatus.INIT) {
|
||||
codeBlock.execute();
|
||||
this.status = LifeCycleStatus.RUN;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void destroy(CodeBlock codeBlock) {
|
||||
if (this.status != LifeCycleStatus.DESTROY) {
|
||||
codeBlock.execute();
|
||||
this.status = LifeCycleStatus.DESTROY;
|
||||
}
|
||||
}
|
||||
|
||||
public static LifeCycleManager create() {
|
||||
return new LifeCycleManager();
|
||||
}
|
||||
|
||||
public LifeCycleStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.context;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: 生命周期状态
|
||||
* @date: 2022/7/2
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum LifeCycleStatus {
|
||||
CREATE(1, "已创建"),
|
||||
INIT(2, "已初始化"),
|
||||
RUN(3, "运行"),
|
||||
DESTROY(4, "已销毁");
|
||||
|
||||
private Integer status;
|
||||
private String desc;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.exception;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/1
|
||||
*/
|
||||
public class BeanException extends InternalException {
|
||||
|
||||
public BeanException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BeanException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,4 +33,7 @@ public class InternalException extends RuntimeException {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InternalException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import fun.asgc.neutrino.core.constant.MetaDataConstant;
|
||||
import fun.asgc.neutrino.core.container.ApplicationContainer;
|
||||
import fun.asgc.neutrino.core.container.DefaultApplicationContainer;
|
||||
import fun.asgc.neutrino.core.context.ApplicationConfig;
|
||||
import fun.asgc.neutrino.core.context.ApplicationContext;
|
||||
import fun.asgc.neutrino.core.context.Environment;
|
||||
import fun.asgc.neutrino.core.util.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -64,9 +65,15 @@ public class NeutrinoLauncher {
|
||||
stopWatch.start();
|
||||
|
||||
environmentInit();
|
||||
this.applicationContainer = new DefaultApplicationContainer(environment);
|
||||
// this.applicationContainer = new DefaultApplicationContainer(environment);
|
||||
// SystemUtil.RunContext runContext = SystemUtil.waitProcessDestroy(() -> {
|
||||
// this.applicationContainer.destroy();
|
||||
// log.info("Application already stop.");
|
||||
// });
|
||||
ApplicationContext context = new ApplicationContext(environment);
|
||||
context.run();
|
||||
SystemUtil.RunContext runContext = SystemUtil.waitProcessDestroy(() -> {
|
||||
this.applicationContainer.destroy();
|
||||
context.destroy();
|
||||
log.info("Application already stop.");
|
||||
});
|
||||
|
||||
|
||||
@@ -204,6 +204,12 @@ public abstract class Assert {
|
||||
}
|
||||
}
|
||||
|
||||
public static void notEmpty(String s, String message) {
|
||||
if (StringUtil.isEmpty(s)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array
|
||||
|
||||
@@ -25,13 +25,11 @@ package fun.asgc.neutrino.core.util;
|
||||
import fun.asgc.neutrino.core.container.BeanContainer;
|
||||
import fun.asgc.neutrino.core.context.ApplicationConfig;
|
||||
import fun.asgc.neutrino.core.context.ApplicationContext;
|
||||
import fun.asgc.neutrino.core.context.Bean;
|
||||
import fun.asgc.neutrino.core.bean.BeanWrapper;
|
||||
import fun.asgc.neutrino.core.context.Environment;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -64,7 +62,7 @@ public class BeanManager {
|
||||
return context;
|
||||
} else {
|
||||
if (null != context.getBeanContainer()) {
|
||||
Bean bean = context.getBeanContainer().getBean(name);
|
||||
BeanWrapper bean = context.getBeanContainer().getBean(name);
|
||||
if (null != bean) {
|
||||
if (!bean.hasInstance()) {
|
||||
bean.newInstance(context);
|
||||
@@ -90,7 +88,7 @@ public class BeanManager {
|
||||
return (T)context;
|
||||
} else {
|
||||
if (null != context.getBeanContainer()) {
|
||||
Bean bean = context.getBeanContainer().getBean(clazz);
|
||||
BeanWrapper bean = context.getBeanContainer().getBean(clazz);
|
||||
if (null != bean) {
|
||||
if (!bean.hasInstance()) {
|
||||
bean.newInstance(context);
|
||||
@@ -113,7 +111,7 @@ public class BeanManager {
|
||||
return null;
|
||||
}
|
||||
return context.getBeanContainer().beanList().stream()
|
||||
.map(Bean::getClazz)
|
||||
.map(BeanWrapper::getType)
|
||||
.filter(item -> superClass.isAssignableFrom(item))
|
||||
.map(item -> (T)getBean(item))
|
||||
.filter(Objects::nonNull)
|
||||
|
||||
@@ -25,6 +25,7 @@ package fun.asgc.neutrino.core.util;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -60,6 +61,11 @@ public class CollectionUtil {
|
||||
return !isEmpty(collection);
|
||||
}
|
||||
|
||||
public static boolean notEmpty(Map map) {
|
||||
return !isEmpty(map);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param source
|
||||
@@ -338,4 +344,21 @@ public class CollectionUtil {
|
||||
}
|
||||
return elements.toArray(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将另一个集合的内容添加到指定集合中
|
||||
* @param supplier
|
||||
* @param list
|
||||
*/
|
||||
public static <T> List<T> addAll(Supplier<List<T>> supplier, List<T> ...list) {
|
||||
List<T> res = supplier.get();
|
||||
if (ArrayUtil.notEmpty(list)) {
|
||||
for (List<T> l : list) {
|
||||
if (null != l && CollectionUtil.notEmpty(l)) {
|
||||
res.addAll(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.util;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 函数工具
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/1
|
||||
*/
|
||||
public class FunctionUtil {
|
||||
|
||||
/**
|
||||
* 获取第一个非空值
|
||||
* @param suppliers
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T getFirstNotNull(Supplier<T> ...suppliers) {
|
||||
T res;
|
||||
if (ArrayUtil.notEmpty(suppliers)) {
|
||||
for (Supplier<T> supplier : suppliers) {
|
||||
if (null != supplier) {
|
||||
res = supplier.get();
|
||||
if (null != res) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,4 +39,10 @@ public class Dog {
|
||||
public String say(String msg) {
|
||||
return "狗说:" + msg;
|
||||
}
|
||||
|
||||
// static 测试static方法
|
||||
public int calc(int x, int y) {
|
||||
System.out.println("计算 " + x + " + " + "y");
|
||||
return x + y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,4 +54,10 @@ public class Test1 {
|
||||
System.out.println(cat.calc(10, 6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dogCalc() {
|
||||
Dog dog = Aop.get(Dog.class);
|
||||
System.out.println(dog.calc(1, 2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.bean;
|
||||
|
||||
import fun.asgc.neutrino.core.aop.Animal;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/7/1
|
||||
*/
|
||||
public class BeanIdentityTest {
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
System.out.println(new BeanIdentity("animal", Animal.class).equals(new BeanIdentity("animal", Animal.class)));
|
||||
System.out.println(new BeanIdentity("animal", Animal.class) == new BeanIdentity("animal", Animal.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
Map<BeanIdentity, String> map = new HashMap<>();
|
||||
map.put(new BeanIdentity("1", String.class), "1");
|
||||
map.put(new BeanIdentity("1", String.class), "2");
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user