From 2e726b6513a4ccabc19325a70a9d3c88a1781d15 Mon Sep 17 00:00:00 2001 From: aoshiguchen <1052045476@qq.com> Date: Mon, 4 Jul 2022 17:47:38 +0800 Subject: [PATCH] =?UTF-8?q?bean=E5=AE=B9=E5=99=A8=E9=87=8D=E6=9E=84?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E6=8C=89=E7=85=A7=E5=90=8D=E5=AD=97?= =?UTF-8?q?=E3=80=81=E7=B1=BB=E5=9E=8B=E3=80=81=E5=90=8D=E5=AD=97+?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E4=B8=89=E7=A7=8D=E6=96=B9=E5=BC=8F=E6=B3=A8?= =?UTF-8?q?=E5=85=A5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../neutrino/core/annotation/Autowired.java | 4 + .../java/fun/asgc/neutrino/core/aop/Aop.java | 17 +- .../interceptor/InnerGlobalInterceptor.java | 2 +- .../core/aop/proxy/AsgcProxyFactory.java | 10 +- .../aop/proxy/JdkDynamicProxyFactory.java | 8 +- .../neutrino/core/aop/proxy/ProxyFactory.java | 2 +- .../core/bean/AbstractBeanFactory.java | 162 +++++++++++++++--- .../asgc/neutrino/core/bean/BeanFactory.java | 21 +++ .../asgc/neutrino/core/bean/BeanIdentity.java | 5 +- .../core/bean/BeanInstantiationMode.java | 41 +++++ .../neutrino/core/bean/BeanMatchMode.java | 41 +++++ .../asgc/neutrino/core/bean/BeanWrapper.java | 17 +- .../asgc/neutrino/core/bean/FactoryBean.java | 44 +++++ .../neutrino/core/bean/SimpleBeanFactory.java | 155 +++++++++++++---- .../core/context/ApplicationContext.java | 5 +- .../core/launcher/NeutrinoLauncher.java | 16 +- .../asgc/neutrino/core/util/ClassUtil.java | 5 + .../fun/asgc/neutrino/core/util/LockUtil.java | 26 +++ .../fun/asgc/neutrino/core/util/TypeUtil.java | 52 ++++++ .../fun/asgc/neutrino/core/aop/Test1.java | 10 +- .../fun/asgc/neutrino/core/aop/Test2.java | 12 +- .../fun/asgc/neutrino/core/aop/Test3.java | 35 +++- .../neutrino/core/bean/BeanIdentityTest.java | 10 ++ .../asgc/neutrino/core/bean/test1/Animal.java | 35 ++++ .../asgc/neutrino/core/bean/test1/Cat.java | 44 +++++ .../asgc/neutrino/core/bean/test1/Dog.java | 37 ++++ .../neutrino/core/bean/test1/Launcher.java | 81 +++++++++ .../asgc/neutrino/core/db/mapper/Test1.java | 4 + .../neutrino/core/util/ClassUtilTest.java | 38 ++++ 29 files changed, 833 insertions(+), 106 deletions(-) create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanInstantiationMode.java create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanMatchMode.java create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/FactoryBean.java create mode 100644 neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Animal.java create mode 100644 neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Cat.java create mode 100644 neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Dog.java create mode 100644 neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Launcher.java create mode 100644 neutrino-core/src/test/java/fun/asgc/neutrino/core/util/ClassUtilTest.java diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/annotation/Autowired.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/annotation/Autowired.java index a860eea9..1c781ded 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/annotation/Autowired.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/annotation/Autowired.java @@ -22,6 +22,8 @@ package fun.asgc.neutrino.core.annotation; +import fun.asgc.neutrino.core.bean.BeanMatchMode; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -36,4 +38,6 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) public @interface Autowired { String value() default ""; + BeanMatchMode matchMode() default BeanMatchMode.ByTypeName; + Class[] parameterTypes() default {}; } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/Aop.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/Aop.java index 41a1e960..ad475f57 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/Aop.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/Aop.java @@ -38,17 +38,12 @@ public class Aop { private static ProxyStrategy proxyStrategy = ProxyStrategy.AUTO; private static final Cache, Object> proxyBeanCache = new MemoryCache<>(); - public static T get(Class clazz) { - try { - return (T)LockUtil.doubleCheckProcess(() -> !proxyBeanCache.containsKey(clazz), - clazz, - () -> proxyBeanCache.set(clazz, getProxyFactory(clazz).get(clazz)), - () -> proxyBeanCache.get(clazz) - ); - } catch (Exception e) { - e.printStackTrace(); - } - return null; + public static T get(Class clazz) throws Exception { + return (T)LockUtil.doubleCheckProcess(() -> !proxyBeanCache.containsKey(clazz), + clazz, + () -> proxyBeanCache.set(clazz, getProxyFactory(clazz).get(clazz)), + () -> proxyBeanCache.get(clazz) + ); } /** diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/interceptor/InnerGlobalInterceptor.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/interceptor/InnerGlobalInterceptor.java index f3844a64..9d029e8c 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/interceptor/InnerGlobalInterceptor.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/interceptor/InnerGlobalInterceptor.java @@ -43,7 +43,7 @@ public class InnerGlobalInterceptor implements Interceptor { private static final InterceptorWrapper interceptorWrapper = new InterceptorWrapper(InnerGlobalInterceptor.class.getSimpleName()); public InnerGlobalInterceptor() { - System.out.println("aaaaa"); + } @Override diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/AsgcProxyFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/AsgcProxyFactory.java index 6c5e5b9a..74b14dbf 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/AsgcProxyFactory.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/AsgcProxyFactory.java @@ -49,14 +49,10 @@ public class AsgcProxyFactory implements ProxyFactory { private ProxyClassLoader classLoader = new ProxyClassLoader(); @Override - public T get(Class clazz) { + public T get(Class clazz) throws Exception { Assert.notNull(clazz, "被代理类不能为空!"); Assert.isTrue(canProxy(clazz), String.format("类[%s]无法被代理!", clazz.getName())); - try { - return doGet(clazz); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } + return doGet(clazz); } @Override @@ -114,7 +110,7 @@ public class AsgcProxyFactory implements ProxyFactory { Method[] methods = clazz.getMethods(); if (ArrayUtil.notEmpty(methods)) { for (Method method : methods) { - if (Modifier.isFinal(method.getModifiers())) { + if (Modifier.isFinal(method.getModifiers()) || Modifier.isStatic(method.getModifiers())) { continue; } Long methodId = ProxyCache.setMethod(method); diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/JdkDynamicProxyFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/JdkDynamicProxyFactory.java index f01cc922..b42f597b 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/JdkDynamicProxyFactory.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/JdkDynamicProxyFactory.java @@ -37,14 +37,10 @@ import java.util.Set; public class JdkDynamicProxyFactory implements ProxyFactory { @Override - public T get(Class clazz) { + public T get(Class clazz) throws Exception { Assert.notNull(clazz, "被代理类不能为空!"); Assert.isTrue(canProxy(clazz), String.format("类[%s]无法被代理!", clazz.getName())); - try { - return doGet(clazz); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } + return doGet(clazz); } private T doGet(Class clazz) throws ReflectiveOperationException { diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/ProxyFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/ProxyFactory.java index a13b8d53..a79729e0 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/ProxyFactory.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/ProxyFactory.java @@ -33,7 +33,7 @@ public interface ProxyFactory { * @param * @return */ - T get(Class clazz); + T get(Class clazz) throws Exception; /** * 是否能被代理 diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/AbstractBeanFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/AbstractBeanFactory.java index 3af708fa..fe0e7edf 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/AbstractBeanFactory.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/AbstractBeanFactory.java @@ -52,6 +52,10 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, * bean缓存 */ protected Map beanCache; + /** + * 工厂bean缓存 + */ + protected Map factoryBeanCache; /** * 互斥锁 */ @@ -73,6 +77,7 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, Assert.notNull(name, "工厂名称不能为空"); this.parent = parent; this.beanCache = new ConcurrentHashMap<>(256); + this.factoryBeanCache = new ConcurrentHashMap<>(256); this.name = name; if (null == parent) { this.mutex = new Object(); @@ -89,6 +94,14 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, return null != bean ? bean : doGetBean(name, args); } + + @Override + public T getBeanByName(Class type, String name, Object... args) { + Assert.notEmpty(name, "Bean名称不能为空!"); + T bean = (null == parent) ? null : parent.getBeanByName(type, name, args); + return null != bean ? bean : doGetBeanByName(type, name, args); + } + @Override public T getBean(Class type, Object... args) throws BeanException { Assert.notNull(type, "Bean类型不能为空!"); @@ -101,7 +114,7 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, 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); + return null != bean ? bean : doGetBeanByTypeAndName(type, name, args); } @Override @@ -118,6 +131,14 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, ); } + @Override + public List getBeanListByName(Class type, String name, Object... args) throws BeanException { + return CollectionUtil.addAll(() -> new LinkedList<>(), + null == parent ? null : parent.getBeanListByName(type, name, args), + doGetBeanListByName(type, name, args) + ); + } + @Override public boolean hasBean(Class type, String name) { boolean res = (null != parent) ? parent.hasBean(type, name) : false; @@ -188,7 +209,17 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, } else if (beanList.size() > 1) { throw new BeanException(String.format("Bean[name:%s] 存在多个实例!", name)); } - return getOrNew(beanList.get(0)); + return getOrNew(beanList.get(0), args); + } + + private T doGetBeanByName(Class type, String name, Object... args) throws BeanException { + List beanList = findBeanList(type, 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), args); } private T doGetBean(Class type, Object... args) throws BeanException { @@ -198,15 +229,15 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, } else if (beanList.size() > 1) { throw new BeanException(String.format("Bean[type:%s] 存在多个实例!", type)); } - return getOrNew(beanList.get(0)); + return getOrNew(beanList.get(0), args); } - private T doGetBeanByNameAndType(String name, Class type, Object... args) throws BeanException { + private T doGetBeanByTypeAndName(Class type, String name, Object... args) throws BeanException { BeanWrapper bean = findBean(type, name); if (null == bean) { return null; } - return getOrNew(bean); + return getOrNew(bean, args); } private List doGetBeanList(Class type, Object... args) throws BeanException { @@ -214,7 +245,15 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, if (CollectionUtil.isEmpty(beanList)) { return null; } - return getOrNew(beanList); + return getOrNew(beanList, args); + } + + private List doGetBeanListByName(Class type, String name, Object... args) throws BeanException { + List beanList = findBeanList(type, name); + if (CollectionUtil.isEmpty(beanList)) { + return null; + } + return getOrNew(beanList, args); } private boolean doHasBean(Class type, String name) { @@ -265,6 +304,22 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, return beanList; } + /** + * 查找bean + * @param type + * @return + */ + private List findBeanList(Class type, String name) { + Assert.notNull(type, "bean的类型不能为空!"); + List beanList = new LinkedList<>(); + for (BeanIdentity identity : beanCache.keySet()) { + if (type.isAssignableFrom(identity.getType()) && identity.getName().equals(name)) { + beanList.add(beanCache.get(identity)); + } + } + return beanList; + } + /** * 查找bean * @param type @@ -281,8 +336,36 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, * 新增一个bean * @param bean */ - protected void addBean(BeanWrapper bean) { + protected void addBean(BeanWrapper bean) throws BeanException { beanCache.put(new BeanIdentity(bean.getName(), bean.getType()), bean); + if (FactoryBean.class.isAssignableFrom(bean.getType())) { + // 工厂bean + if (factoryBeanCache.containsKey(bean.getBeanIdentity())) { + throw new BeanException(String.format("Bean[type:%s name:%s] 存在多个factoryBean!", bean.getType().getName(), bean.getName())); + } + factoryBeanCache.put(bean.getBeanIdentity(), bean); + } + } + + /** + * 获取bean的工厂 + * @param bean + * @return + */ + protected FactoryBean getFactory(BeanWrapper bean) throws BeanException { + BeanWrapper factoryBeanWrapper = factoryBeanCache.get(bean.getIdentity()); + if (null == factoryBeanWrapper) { + return null; + } + dependencyCheck(factoryBeanWrapper); + newInstance(factoryBeanWrapper); + inject(factoryBeanWrapper); + factoryBeanWrapper.init(); + + if (BeanStatus.INIT == factoryBeanWrapper.getStatus() || BeanStatus.RUNNING == factoryBeanWrapper.getStatus()) { + return (FactoryBean)factoryBeanWrapper.getInstance(); + } + throw new BeanException(String.format("Bean[type:%s name%s] 获取工厂 Beanfactory[type:%s name:%s]异常!", bean.getType().getName(), bean.getName(), factoryBeanWrapper.getType().getName(), factoryBeanWrapper.getName())); } @Override @@ -318,19 +401,22 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, * @return * @throws BeanException */ - protected List getOrNew(List beanList) throws BeanException { - List list = new LinkedList<>(); + protected List getOrNew(List beanList, Object... args) throws BeanException { if (CollectionUtil.isEmpty(beanList)) { - return list; + return null; } - 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())); + dependencyCheck(beanList); + newInstance(beanList, args); + inject(beanList); + beanList.forEach(beanWrapper -> beanWrapper.init()); + + for (BeanWrapper beanWrapper : beanList) { + if (beanWrapper.getStatus().getStatus() < BeanStatus.INIT.getStatus()) { + throw new BeanException(String.format("Bean[type:%s name:%s]实例化失败!", beanWrapper.getType().getName(), beanWrapper.getName())); } - list.add(instance); } - return list; + + return beanList.stream().filter(beanWrapper -> BeanStatus.DESTROY != beanWrapper.getStatus()).map(beanWrapper -> (T)beanWrapper.getInstance()).collect(Collectors.toList()); } /** @@ -370,7 +456,7 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, * @param * @return */ - protected T getOrNew(BeanWrapper bean) throws BeanException { + protected T getOrNew(BeanWrapper bean, Object... args) throws BeanException { try { return (T)LockUtil.doubleCheckProcess( () -> !(BeanStatus.INIT == bean.getStatus() || BeanStatus.RUNNING == bean.getStatus()), @@ -396,13 +482,49 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, } } + /** + * 依赖关系检测 + * @param beanList + * @return + * @throws BeanException + */ + protected void dependencyCheck(List beanList) throws BeanException { + for (BeanWrapper beanWrapper : beanList) { + dependencyCheck(beanWrapper); + } + } + + /** + * 实例化 + * @param beanList + * @return + * @throws BeanException + */ + protected void newInstance(List beanList, Object... args) throws BeanException { + for (BeanWrapper beanWrapper : beanList) { + newInstance(beanWrapper, args); + } + } + + /** + * 注入 + * @param beanList + * @return + * @throws BeanException + */ + protected void inject(List beanList) throws BeanException { + for (BeanWrapper beanWrapper : beanList) { + inject(beanWrapper); + } + } + /** * 依赖关系检测 * @param bean * @return * @throws BeanException */ - protected abstract void dependencyCheck(BeanWrapper bean) throws Exception; + protected abstract void dependencyCheck(BeanWrapper bean) throws BeanException; /** * 实例化 @@ -411,7 +533,7 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, * @return * @throws BeanException */ - protected abstract T newInstance(BeanWrapper bean) throws BeanException; + protected abstract T newInstance(BeanWrapper bean, Object... args) throws BeanException; /** * 注入 @@ -419,5 +541,5 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry, * @return * @throws BeanException */ - protected abstract void inject(BeanWrapper bean) throws Exception; + protected abstract void inject(BeanWrapper bean) throws BeanException; } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanFactory.java index b106cd9a..5d365a3b 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanFactory.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanFactory.java @@ -41,6 +41,16 @@ public interface BeanFactory { */ T getBean(String name, Object... args) throws BeanException; + /** + * 尝试根据名称获取bean,此处的type不做强制限定,可以是bean的接口或超类型 + * @param type + * @param name + * @param args + * @param + * @return + */ + T getBeanByName(Class type, String name, Object... args); + /** * 尝试根据类型获取bean * @param type @@ -81,4 +91,15 @@ public interface BeanFactory { * @throws BeanException */ List getBeanList(Class type, Object... args) throws BeanException; + + /** + * 尝试根据名称获取bean,此处的type不做强制限定,可以是bean的接口或超类型 + * @param type + * @param name + * @param args + * @param + * @return + * @throws BeanException + */ + List getBeanListByName(Class type, String name, Object... args) throws BeanException; } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanIdentity.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanIdentity.java index f1f30c24..6963d5ca 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanIdentity.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanIdentity.java @@ -50,7 +50,7 @@ public class BeanIdentity implements Identity { Assert.notNull(type, "类型不能为空!"); this.name = name; this.type = type; - this.identityHashCode = System.identityHashCode(name) + System.identityHashCode(type); + this.identityHashCode = System.identityHashCode(type); } /** @@ -79,6 +79,9 @@ public class BeanIdentity implements Identity { if (null == obj) { return false; } + if (obj == this) { + return true; + } if (!(obj instanceof BeanIdentity)) { return false; } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanInstantiationMode.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanInstantiationMode.java new file mode 100644 index 00000000..026c2404 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanInstantiationMode.java @@ -0,0 +1,41 @@ +/** + * 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; + +/** + * Bean实例化的方式 + * @author: aoshiguchen + * @date: 2022/7/4 + */ +@Getter +@AllArgsConstructor +public enum BeanInstantiationMode { + // newInstance + DIRECT(1, "直接"), + METHOD(2, "方法"), + FACTORY(3, "工厂"); + private Integer mode; + private String desc; +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanMatchMode.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanMatchMode.java new file mode 100644 index 00000000..fba32ba2 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanMatchMode.java @@ -0,0 +1,41 @@ +/** + * 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; + +/** + * bean的匹配模式 + * @author: aoshiguchen + * @date: 2022/7/4 + */ +@Getter +@AllArgsConstructor +public enum BeanMatchMode { + ByType(1, "根据类型匹配"), + ByName(2, "根据名称匹配"), + ByTypeName(3, "根据类型+名称匹配"); + + private Integer mode; + private String desc; +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanWrapper.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanWrapper.java index db04ddfa..6b12df22 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanWrapper.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/BeanWrapper.java @@ -56,6 +56,7 @@ public class BeanWrapper implements LifeCycle { private volatile boolean isInit; private BeanStatus status; private boolean isLazy; + private BeanIdentity beanIdentity; public boolean hasInstance() { return null != instance; @@ -63,12 +64,11 @@ public class BeanWrapper implements LifeCycle { @Override public void init() { - if (isInit) { - return; - } - if (!hasInstance()) { + if (BeanStatus.INJECT != status) { return; } + this.setStatus(BeanStatus.INIT); + log.info("Bean[type:{} name:{}]初始化...", getType().getName(), getName()); isInit = true; Set methods = ReflectUtil.getMethods(type); @@ -239,4 +239,13 @@ public class BeanWrapper implements LifeCycle { public void run() { } + + public BeanIdentity getIdentity() { + return LockUtil.doubleCheckProcessForNoException( + () -> null == beanIdentity, + this, + () -> beanIdentity = new BeanIdentity(this.name, this.type), + () -> beanIdentity + ); + } } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/FactoryBean.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/FactoryBean.java new file mode 100644 index 00000000..e11f60c2 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/FactoryBean.java @@ -0,0 +1,44 @@ +/** + * 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/4 + */ +public interface FactoryBean { + /** + * 获取bean实例 + * @return + * @throws BeanException + */ + T getInstance() throws BeanException; + + /** + * 获取Bean身份 + * @return + */ + BeanIdentity getBeanIdentity(); +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/SimpleBeanFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/SimpleBeanFactory.java index 2f5089b6..e7f4d92a 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/SimpleBeanFactory.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/bean/SimpleBeanFactory.java @@ -21,15 +21,16 @@ */ package fun.asgc.neutrino.core.bean; -import fun.asgc.neutrino.core.annotation.Autowired; -import fun.asgc.neutrino.core.annotation.Lazy; -import fun.asgc.neutrino.core.annotation.Order; +import com.google.common.collect.Lists; +import fun.asgc.neutrino.core.annotation.*; +import fun.asgc.neutrino.core.aop.Aop; import fun.asgc.neutrino.core.exception.BeanException; import fun.asgc.neutrino.core.runner.ApplicationRunner; import fun.asgc.neutrino.core.util.*; import lombok.extern.slf4j.Slf4j; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -68,54 +69,144 @@ public class SimpleBeanFactory extends AbstractBeanFactory { beanWrapper.setOrder(order.value()); } addBean(beanWrapper); + registerBeanForMethod(type); } - @Override - protected void dependencyCheck(BeanWrapper bean) throws Exception { - LockUtil.doubleCheckProcess( - () -> BeanStatus.REGISTER == bean.getStatus(), - bean, - () -> { - Set fieldSet = ReflectUtil.getInheritChainDeclaredFieldSet(bean.getType()); - if (CollectionUtil.notEmpty(fieldSet)) { - fieldSet.forEach(field -> { - Autowired autowired = field.getAnnotation(Autowired.class); - if (null == autowired) { - return; - } - String name = field.getName(); - // TODO - }); - } + /** + * 根据method注册bean + * @param type + */ + private void registerBeanForMethod(Class type) { + Set methods = ReflectUtil.getMethods(type); + if (CollectionUtil.isEmpty(methods)) { + return; + } + for (Method method : methods) { + Bean bean = method.getAnnotation(Bean.class); + if (null == bean) { + continue; } - ); + String beanName = bean.value(); + if (StringUtil.isEmpty(beanName)) { + beanName = method.getName(); + } + Class beanType = method.getReturnType(); + if (method.getParameters().length > 0) { + throw new BeanException(String.format("Bean[type:%s name:%s] 注册失败,Class:%s method:%s 方法不能带参数!", beanType.getName(), beanName, type.getName(), method.getName())); + } + addBean(beanType, beanName); + } } @Override - protected T newInstance(BeanWrapper bean) throws BeanException { + protected void dependencyCheck(BeanWrapper bean) throws BeanException { + try { + LockUtil.doubleCheckProcess( + () -> BeanStatus.REGISTER == bean.getStatus(), + bean, + () -> { + // TODO + bean.setStatus(BeanStatus.DEPENDENCY_CHECKING); + } + ); + } catch (Exception e) { + throw new BeanException(String.format("Bean[type:%s name:%s] 依赖检测异常!", bean.getType().getName(), bean.getName())); + } + } + + @Override + protected T newInstance(BeanWrapper bean, Object... args) throws BeanException { try { return LockUtil.doubleCheckProcess( () -> BeanStatus.DEPENDENCY_CHECKING == bean.getStatus(), bean, () -> { - bean.getClass().newInstance(); + // TODO 此处factoryBean可能还未注入、初始化,需要思考优化 + FactoryBean factoryBean = getFactory(bean); + if (null != factoryBean) { + bean.setInstance(factoryBean.getInstance()); + } else if (ClassUtil.isInterface(bean.getType())) { + bean.setInstance(Aop.get(bean.getType())); + } else if(bean.getType().isAnnotationPresent(Configuration.class)) { + bean.setInstance(ConfigUtil.getYmlConfig(bean.getType())); + } else { + if (ClassUtil.hasNoArgsConstructor(bean.getType())) { + bean.setInstance(Aop.get(bean.getType())); + } else { + // TODO 暂不支持有参构造器 + throw new BeanException(String.format("Bean[type:%s name:%s] 没有无参构造器,实例化失败!", bean.getType().getName(), bean.getName())); + } + } + if (null != bean.getInstance()) { + bean.setStatus(BeanStatus.INSTANCE); + } }, () -> (T)bean.getInstance() ); - } catch (Exception e) { + } catch (BeanException e) { + throw e; + }catch (Exception e) { throw new BeanException(String.format("Bean[type:%s name:%s] 实例化异常", bean.getType().getName(), bean.getName()), e); } } @Override - protected void inject(BeanWrapper bean) throws Exception { - LockUtil.doubleCheckProcess( - () -> BeanStatus.INSTANCE == bean.getStatus(), - bean, - () -> { - // TODO - } - ); + protected void inject(BeanWrapper bean) throws BeanException { + try { + LockUtil.doubleCheckProcess( + () -> BeanStatus.INSTANCE == bean.getStatus(), + bean, + () -> { + Set fieldSet = ReflectUtil.getInheritChainDeclaredFieldSet(bean.getType()); + if (CollectionUtil.isEmpty(fieldSet)) { + bean.setStatus(BeanStatus.INJECT); + return; + } + for (Field field : fieldSet) { + Autowired autowired = field.getAnnotation(Autowired.class); + if (null == autowired) { + continue; + } + String beanName = autowired.value(); + if (StringUtil.isEmpty(beanName)) { + beanName = field.getName(); + } + Class parameterType = autowired.parameterTypes().length == 0 ? Object.class : autowired.parameterTypes()[0]; + BeanMatchMode matchMode = autowired.matchMode(); + Object obj = null; + if (matchMode == BeanMatchMode.ByType) { + if (TypeUtil.isListable(field.getType())) { + List list = getBeanList(parameterType); + obj = TypeUtil.listTo(list, field.getType()); + } else { + obj = getBean(field.getType()); + } + } else if(matchMode == BeanMatchMode.ByName) { + if (TypeUtil.isListable(field.getType())) { + List list = getBeanListByName(parameterType, beanName); + obj = TypeUtil.listTo(list, field.getType()); + } else { + obj = getBeanByName(field.getType(), beanName); + } + } else if (matchMode == BeanMatchMode.ByTypeName) { + obj = getBeanByTypeAndName(field.getType(), beanName); + if (TypeUtil.isListable(field.getType())) { + obj = TypeUtil.listTo(Lists.newArrayList(obj), field.getType()); + } + } + if (null == obj) { + throw new BeanException(String.format("Bean[type:%s name:%s field:%s] 注入异常", bean.getType().getName(), bean.getName(), field.getName())); + } + ReflectUtil.setFieldValue(field, bean.getInstance(), obj); + } + bean.setStatus(BeanStatus.INJECT); + } + ); + } catch (BeanException e){ + throw e; + }catch (Exception e) { + throw new BeanException(String.format("Bean[type:%s name:%s] 注入异常", bean.getType().getName(), bean.getName()), e); + } } @Override diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/context/ApplicationContext.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/context/ApplicationContext.java index 49d55a10..2a226b09 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/context/ApplicationContext.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/context/ApplicationContext.java @@ -147,6 +147,9 @@ public class ApplicationContext implements LifeCycle { List applicationRunnerList = this.applicationBeanFactory.getBeanList(ApplicationRunner.class); if (CollectionUtil.notEmpty(applicationRunnerList)) { applicationRunnerList.forEach(applicationRunner -> applicationRunner.run(this.environment.getMainArgs())); - } +// for (ApplicationRunner runner : applicationRunnerList) { +// runner.run(this.environment.getMainArgs()); +// } + } } } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/launcher/NeutrinoLauncher.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/launcher/NeutrinoLauncher.java index 61f097aa..f5c09df9 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/launcher/NeutrinoLauncher.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/launcher/NeutrinoLauncher.java @@ -65,17 +65,17 @@ public class NeutrinoLauncher { stopWatch.start(); environmentInit(); - 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(); +// this.applicationContainer = new DefaultApplicationContainer(environment); // SystemUtil.RunContext runContext = SystemUtil.waitProcessDestroy(() -> { -// context.destroy(); +// this.applicationContainer.destroy(); // log.info("Application already stop."); // }); + ApplicationContext context = new ApplicationContext(environment); + context.run(); + SystemUtil.RunContext runContext = SystemUtil.waitProcessDestroy(() -> { + context.destroy(); + log.info("Application already stop."); + }); stopWatch.stop(); printLog(environment, stopWatch); diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/ClassUtil.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/ClassUtil.java index 2871e203..da8cca07 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/ClassUtil.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/ClassUtil.java @@ -38,6 +38,7 @@ import java.net.URLClassLoader; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.stream.Stream; /** * @@ -239,4 +240,8 @@ public class ClassUtil { public static boolean isInterface(Class clazz) { return clazz.isInterface(); } + + public static boolean hasNoArgsConstructor(Class clazz) { + return Stream.of(clazz.getConstructors()).filter(c -> c.getParameterCount() == 0).count() > 0; + } } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/LockUtil.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/LockUtil.java index cf4a6d9c..5ba2d0e8 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/LockUtil.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/LockUtil.java @@ -50,6 +50,20 @@ public class LockUtil { } } + /** + * 双重校验处理 + * @param isLock + * @param lock + * @param lockProcess + */ + public static void doubleCheckProcessForNoException(BooleanSupplier isLock, Object lock, CodeBlock lockProcess) { + try { + doubleCheckProcess(isLock, lock, lockProcess); + } catch (Exception e) { + // ignore + } + } + /** * 双重校验处理 * @param isLock @@ -61,4 +75,16 @@ public class LockUtil { doubleCheckProcess(isLock, lock, lockProcess); return nonLockProcess.get(); } + + /** + * 双重校验处理 + * @param isLock + * @param lock + * @param lockProcess + * @param nonLockProcess + */ + public static T doubleCheckProcessForNoException(BooleanSupplier isLock, Object lock, CodeBlock lockProcess, Supplier nonLockProcess) { + doubleCheckProcessForNoException(isLock, lock, lockProcess); + return nonLockProcess.get(); + } } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeUtil.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeUtil.java index b8559c01..aa9f18f2 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeUtil.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeUtil.java @@ -28,6 +28,7 @@ import fun.asgc.neutrino.core.type.TypeMatchers; import java.lang.reflect.Field; import java.util.*; +import java.util.stream.Collectors; /** * @@ -491,6 +492,57 @@ public class TypeUtil { return defaultValueMap.get(clazz); } + /** + * 是否是集合类型 + * @param clazz + * @return + */ + public static boolean isCollection(Class clazz) { + return Collection.class.isAssignableFrom(clazz); + } + + /** + * 是否可列举 + * @param clazz + * @return + */ + public static boolean isListable(Class clazz) { + return clazz.isArray() || isCollection(clazz); + } + + /** + * 是否是list + * @param clazz + * @return + */ + public static boolean isList(Class clazz) { + return List.class.isAssignableFrom(clazz); + } + + /** + * list转成其他形式 + * @param list + * @param targetType + * @return + */ + public static Object listTo(List list, Class targetType) { + if (null == list) { + return null; + } + if (isList(targetType)) { + return list; + } + // 数组 + if (targetType.isArray()) { + return list.toArray(); + } + // set + if (Set.class.isAssignableFrom(targetType)) { + return list.stream().collect(Collectors.toSet()); + } + return null; + } + /** * 获取继承层级 * 此处假定继承层级最多为100层,避免计算太过耗时 diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test1.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test1.java index 532b0851..cd35308c 100644 --- a/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test1.java +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test1.java @@ -31,31 +31,31 @@ import org.junit.Test; public class Test1 { @Test - public void dogCall() { + public void dogCall() throws Exception { Dog dog = Aop.get(Dog.class); dog.call(); } @Test - public void dogSay() { + public void dogSay() throws Exception { Dog dog = Aop.get(Dog.class); System.out.println(dog.say("hello")); } @Test - public void catClimb() { + public void catClimb() throws Exception { Cat cat = Aop.get(Cat.class); cat.climb(); } @Test - public void catCalc() { + public void catCalc() throws Exception { Cat cat = Aop.get(Cat.class); System.out.println(cat.calc(10, 6)); } @Test - public void dogCalc() { + public void dogCalc() throws Exception { Dog dog = Aop.get(Dog.class); System.out.println(dog.calc(1, 2)); } diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test2.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test2.java index bee9a392..c00436e7 100644 --- a/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test2.java +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test2.java @@ -78,38 +78,38 @@ public class Test2 { } @Test - public void eat() { + public void eat() throws Exception { Panda panda = Aop.get(Panda.class); panda.eat(); } @Test - public void play() { + public void play() throws Exception { Panda panda = Aop.get(Panda.class); panda.play("滑板"); } @Test - public void division() { + public void division() throws Exception { Panda panda = Aop.get(Panda.class); System.out.println(panda.division(10, 5)); panda.division(10, 0); } @Test - public void say() { + public void say() throws Exception { Panda panda = Aop.get(Panda.class); panda.say("hello"); } @Test - public void request() { + public void request() throws Exception { Panda panda = Aop.get(Panda.class); panda.request("xxx", "yyy"); } @Test - public void up() { + public void up() throws Exception { Panda panda = Aop.get(Panda.class); try { panda.up(); diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test3.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test3.java index c293dee9..9f88b2d5 100644 --- a/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test3.java +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/aop/Test3.java @@ -21,10 +21,10 @@ */ package fun.asgc.neutrino.core.aop; -import fun.asgc.neutrino.core.aop.proxy.Proxy; import fun.asgc.neutrino.core.util.ReflectUtil; import org.junit.Test; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** @@ -35,7 +35,7 @@ import java.lang.reflect.Method; public class Test3 { @Test - public void test1() { + public void test1() throws Exception { Animal animal = Aop.get(Animal.class); // Animal animal = Proxy.getProxyFactory(ProxyStrategy.ASGC_PROXY).get(Animal.class); System.out.println(animal); @@ -43,7 +43,7 @@ public class Test3 { } @Test - public void test2() { + public void test2() throws Exception { Mammal mammal = Aop.get(Mammal.class); mammal.crawl(); @@ -55,4 +55,33 @@ public class Test3 { Bear bear = Aop.get(Bear.class); bear.up(); } + + @Test + public void test4() throws InvocationTargetException, IllegalAccessException { + Method hello1 = ReflectUtil.getMethods(A.class).stream().filter(m -> m.getName().equals("hello1")).findFirst().get(); + Method hello11 = ReflectUtil.getMethods(B.class).stream().filter(m -> m.getName().equals("hello1")).findFirst().get(); + A a = new A(); + B b = new B(); +// hello1.invoke(a); +// hello1.invoke(b); + hello11.invoke(a); // 异常 + hello11.invoke(b); + } + + public static class A { + public void hello1() { + System.out.println("hello1"); + } + public void hello2() { + System.out.println("hello2"); + } + } + + public static class B extends A { + @Override + public void hello1() { + super.hello1(); + System.out.println("----"); + } + } } diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/BeanIdentityTest.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/BeanIdentityTest.java index 978b8d78..40712ac9 100644 --- a/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/BeanIdentityTest.java +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/BeanIdentityTest.java @@ -22,10 +22,12 @@ package fun.asgc.neutrino.core.bean; import fun.asgc.neutrino.core.aop.Animal; +import fun.asgc.neutrino.core.bean.test1.Cat; import org.junit.Test; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * @@ -48,4 +50,12 @@ public class BeanIdentityTest { System.out.println(map); } + @Test + public void test3() { + Cat cat = new Cat(); + Map a = new ConcurrentHashMap<>(); + a.put(new BeanIdentity("cat", Cat.class), 1); + System.out.println(a.get(new BeanIdentity("cat", Cat.class))); + } + } diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Animal.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Animal.java new file mode 100644 index 00000000..72a5a592 --- /dev/null +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Animal.java @@ -0,0 +1,35 @@ +/** + * 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.test1; + +/** + * + * @author: aoshiguchen + * @date: 2022/7/4 + */ +public class Animal { + + public void call() { + System.out.println("未知动物的叫声"); + } + +} diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Cat.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Cat.java new file mode 100644 index 00000000..25a2144d --- /dev/null +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Cat.java @@ -0,0 +1,44 @@ +/** + * 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.test1; + +import fun.asgc.neutrino.core.annotation.Component; +import fun.asgc.neutrino.core.annotation.Init; + +/** + * + * @author: aoshiguchen + * @date: 2022/7/4 + */ +@Component +public class Cat extends Animal { + + @Init + public void a() { + System.out.println("11111"); + } + + @Override + public void call() { + System.out.println("喵喵喵"); + } +} diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Dog.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Dog.java new file mode 100644 index 00000000..782b4159 --- /dev/null +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Dog.java @@ -0,0 +1,37 @@ +/** + * 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.test1; + +import fun.asgc.neutrino.core.annotation.Component; + +/** + * + * @author: aoshiguchen + * @date: 2022/7/4 + */ +@Component +public class Dog extends Animal { + @Override + public void call() { + System.out.println("汪汪汪"); + } +} diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Launcher.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Launcher.java new file mode 100644 index 00000000..181607f8 --- /dev/null +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/bean/test1/Launcher.java @@ -0,0 +1,81 @@ +/** + * 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.test1; + +import fun.asgc.neutrino.core.annotation.Autowired; +import fun.asgc.neutrino.core.annotation.Destroy; +import fun.asgc.neutrino.core.annotation.Init; +import fun.asgc.neutrino.core.annotation.NeutrinoApplication; +import fun.asgc.neutrino.core.bean.BeanMatchMode; +import fun.asgc.neutrino.core.bean.BeanStatus; +import fun.asgc.neutrino.core.launcher.NeutrinoLauncher; + +import java.util.List; +import java.util.Set; + +/** + * + * @author: aoshiguchen + * @date: 2022/7/4 + */ +@NeutrinoApplication +public class Launcher { + + @Autowired + private Cat cat; + @Autowired(matchMode = BeanMatchMode.ByName, value = "cat") + private Animal cat2; + @Autowired(matchMode = BeanMatchMode.ByType) + private Cat cat3; + @Autowired(matchMode = BeanMatchMode.ByType, parameterTypes = Cat.class) + private List cats1; + @Autowired(value = "cat", matchMode = BeanMatchMode.ByName, parameterTypes = Cat.class) + private List cats2; + + @Autowired + private Dog dog; + @Autowired("dog") + private Dog dog2; + @Autowired(value = "dog", matchMode = BeanMatchMode.ByName, parameterTypes = Dog.class) + private Object[] dogs1; + @Autowired(matchMode = BeanMatchMode.ByType, parameterTypes = Dog.class) + private Set dogs2; + @Autowired(matchMode = BeanMatchMode.ByType, parameterTypes = Animal.class) + private List list; + + @Init + public void init() { + System.out.println("初始化---"); + cat.call(); + dog.call(); + } + + @Destroy + public void destroy() { + System.out.println("销毁---"); + } + + public static void main(String[] args) { + NeutrinoLauncher.run(Launcher.class, args).sync(); + } + +} diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/db/mapper/Test1.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/db/mapper/Test1.java index 5dd04d93..8a4eadb5 100644 --- a/neutrino-core/src/test/java/fun/asgc/neutrino/core/db/mapper/Test1.java +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/db/mapper/Test1.java @@ -38,6 +38,10 @@ public class Test1 implements ApplicationRunner { @Autowired private TestGlobalExceptionHandler testGlobalExceptionHandler; + public Test1() { + System.out.println("aaa"); + } + @Init public void init() { log.info("初始化,注册全局异常拦截器{}...", testGlobalExceptionHandler.hashCode()); diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/util/ClassUtilTest.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/util/ClassUtilTest.java new file mode 100644 index 00000000..75a24b03 --- /dev/null +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/util/ClassUtilTest.java @@ -0,0 +1,38 @@ +/** + * 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 org.junit.Test; + +/** + * + * @author: aoshiguchen + * @date: 2022/7/4 + */ +public class ClassUtilTest { + + @Test + public void hasNoArgsConstructor() { + System.out.println(ClassUtil.hasNoArgsConstructor(ClassUtilTest.class)); + } + +}