From 8972b11a9b5a380db0029ee9f193a5d5dd91f6ac Mon Sep 17 00:00:00 2001 From: Dung Ta Van Date: Fri, 22 Nov 2024 14:04:20 +0700 Subject: [PATCH] fix issue 110 --- .../ezyfox/bean/EzySingletonFactory.java | 2 + .../tvd12/ezyfox/bean/impl/EzyBeanKey.java | 2 +- .../bean/impl/EzyByFieldSingletonLoader.java | 11 +++- .../bean/impl/EzyByMethodSingletonLoader.java | 8 ++- .../EzyConfigurationFieldSingletonLoader.java | 45 ++++++++++++++ ...EzyConfigurationMethodSingletonLoader.java | 44 +++++++++++++ .../impl/EzySimpleConfigurationLoader.java | 62 +++++++++++++------ .../bean/impl/EzySimpleSingletonFactory.java | 5 ++ .../bean/impl/EzySimpleSingletonLoader.java | 2 +- .../ezyfox/bean/testing/EzyBeanKeyTest.java | 15 +++++ .../EzyByMethodSingletonLoaderTest.java | 4 +- .../V129DeclareTwoBeansSameTypeTest.java | 35 +++++++++++ .../V129EzySimpleConfigurationLoaderTest.java | 58 +++++++++++++++++ .../v129/testing/config/V129BeanConfig.java | 24 +++++++ .../src/test/resources/AllTests.tng.xml | 1 + .../testing/MsgPackSimpleSerializerTest.java | 2 +- 16 files changed, 293 insertions(+), 27 deletions(-) create mode 100644 ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyConfigurationFieldSingletonLoader.java create mode 100644 ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyConfigurationMethodSingletonLoader.java create mode 100644 ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/V129DeclareTwoBeansSameTypeTest.java create mode 100644 ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/V129EzySimpleConfigurationLoaderTest.java create mode 100644 ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/config/V129BeanConfig.java diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/EzySingletonFactory.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/EzySingletonFactory.java index 2aad91c6..735a8341 100644 --- a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/EzySingletonFactory.java +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/EzySingletonFactory.java @@ -14,6 +14,8 @@ public interface EzySingletonFactory { Object getSingleton(String name, Class type); + Object getSingleton(EzyBeanKey key); + Object getSingleton(Map properties); Object getAnnotatedSingleton(Class annotationClass); diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyBeanKey.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyBeanKey.java index 68bed8dc..ae1b77ba 100644 --- a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyBeanKey.java +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyBeanKey.java @@ -40,6 +40,6 @@ public int hashCode() { @Override public String toString() { - return "(" + name + "," + type.getSimpleName() + ")"; + return "(" + name + "," + type.getName() + ")"; } } diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyByFieldSingletonLoader.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyByFieldSingletonLoader.java index 30f574d1..261114b1 100644 --- a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyByFieldSingletonLoader.java +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyByFieldSingletonLoader.java @@ -23,7 +23,13 @@ public EzyByFieldSingletonLoader( Object configurator, Map, EzyMethod> methodsByType ) { - this(beanName, field, configurator, methodsByType, new ArrayList<>()); + this( + beanName, + field, + configurator, + methodsByType, + new ArrayList<>() + ); } public EzyByFieldSingletonLoader( @@ -33,7 +39,8 @@ public EzyByFieldSingletonLoader( Map, EzyMethod> methodsByType, List> stackCallClasses ) { - super(beanName, + super( + beanName, new EzyClass(field.getType()), configurator, methodsByType, diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyByMethodSingletonLoader.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyByMethodSingletonLoader.java index 1def5f0b..13cc1f09 100644 --- a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyByMethodSingletonLoader.java +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyByMethodSingletonLoader.java @@ -22,7 +22,13 @@ public EzyByMethodSingletonLoader( Object configurator, Map, EzyMethod> methodsByType ) { - this(beanName, method, configurator, methodsByType, new ArrayList<>()); + this( + beanName, + method, + configurator, + methodsByType, + new ArrayList<>() + ); } public EzyByMethodSingletonLoader( diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyConfigurationFieldSingletonLoader.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyConfigurationFieldSingletonLoader.java new file mode 100644 index 00000000..9749f405 --- /dev/null +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyConfigurationFieldSingletonLoader.java @@ -0,0 +1,45 @@ +package com.tvd12.ezyfox.bean.impl; + +import com.tvd12.ezyfox.bean.EzyBeanContext; +import com.tvd12.ezyfox.reflect.EzyField; +import com.tvd12.ezyfox.reflect.EzyMethod; + +import java.util.Map; + +public class EzyConfigurationFieldSingletonLoader + extends EzyByFieldSingletonLoader { + + public EzyConfigurationFieldSingletonLoader( + String beanName, + EzyField field, + Object configurator, + Map, EzyMethod> methodsByType + ) { + super( + beanName, + field, + configurator, + methodsByType + ); + } + + @SuppressWarnings("rawtypes") + @Override + protected Object getOrCreateSingleton( + EzyBeanContext context, + String name, + Class[] parameterTypes + ) { + Object singleton = newSingletonByConstructor( + context, + parameterTypes + ); + logger.debug( + "add singleton with name {} of {}, object = {}", + name, + singleton.getClass(), + singleton + ); + return singleton; + } +} diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyConfigurationMethodSingletonLoader.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyConfigurationMethodSingletonLoader.java new file mode 100644 index 00000000..e567b5d9 --- /dev/null +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzyConfigurationMethodSingletonLoader.java @@ -0,0 +1,44 @@ +package com.tvd12.ezyfox.bean.impl; + +import com.tvd12.ezyfox.bean.EzyBeanContext; +import com.tvd12.ezyfox.reflect.EzyMethod; + +import java.util.Map; + +public class EzyConfigurationMethodSingletonLoader + extends EzyByMethodSingletonLoader { + + public EzyConfigurationMethodSingletonLoader( + String beanName, + EzyMethod method, + Object configurator, + Map, EzyMethod> methodsByType + ) { + super( + beanName, + method, + configurator, + methodsByType + ); + } + + @SuppressWarnings("rawtypes") + @Override + protected Object getOrCreateSingleton( + EzyBeanContext context, + String name, + Class[] parameterTypes + ) { + Object singleton = newSingletonByConstructor( + context, + parameterTypes + ); + logger.debug( + "add singleton with name {} of {}, object = {}", + name, + singleton.getClass(), + singleton + ); + return singleton; + } +} diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleConfigurationLoader.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleConfigurationLoader.java index 217d013e..df4b99f2 100644 --- a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleConfigurationLoader.java +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleConfigurationLoader.java @@ -15,6 +15,7 @@ import static com.tvd12.ezyfox.bean.impl.EzyBeanNameParser.getPrototypeName; import static com.tvd12.ezyfox.bean.impl.EzyBeanNameParser.getSingletonName; +import static com.tvd12.ezyfox.io.EzyMaps.newHashMapNewKeys; public class EzySimpleConfigurationLoader extends EzyLoggable @@ -27,11 +28,16 @@ public class EzySimpleConfigurationLoader protected EzySingletonFactory singletonFactory; protected EzyBeanNameTranslator beanNameTranslator; protected Map, EzyMethod> singletonMethods; + protected Map singletonMethodByKey; @Override public EzyConfigurationLoader clazz(Class configClass) { this.clazz = new EzyClass(configClass); - this.singletonMethods = mapSingletonTypeMethods(); + this.singletonMethodByKey = mapSingletonKeyMethods(); + this.singletonMethods = newHashMapNewKeys( + singletonMethodByKey, + EzyBeanKey::getType + ); return this; } @@ -88,19 +94,26 @@ private void addSingletonByFields(Object configurator) { private void addSingletonByField(EzyField field, Object configurator) { String beanName = getSingletonName(field); - Object current = singletonFactory.getSingleton(beanName, field.getType()); + Object current = singletonFactory.getSingleton( + EzyBeanKey.of(beanName, field.getType()) + ); if (current == null) { - EzySingletonLoader loader = new EzyByFieldSingletonLoader(beanName, field, configurator, singletonMethods); + EzySingletonLoader loader = new EzyConfigurationFieldSingletonLoader( + beanName, + field, + configurator, + singletonMethods + ); loader.load(context); } } private void addSingletonByMethods(Object configurator) { - Set> types = new HashSet<>(singletonMethods.keySet()); - for (Class type : types) { - EzyMethod method = singletonMethods.remove(type); + Set keys = new HashSet<>(singletonMethodByKey.keySet()); + for (EzyBeanKey key : keys) { + EzyMethod method = singletonMethodByKey.remove(key); if (method != null) { - logger.debug("add singleton of {} with method {}", type, method); + logger.debug("add singleton of {} with method {}", key, method); addSingletonByMethod(method, configurator); } } @@ -108,9 +121,11 @@ private void addSingletonByMethods(Object configurator) { private void addSingletonByMethod(EzyMethod method, Object configurator) { String beanName = getSingletonName(method); - Object current = singletonFactory.getSingleton(beanName, method.getReturnType()); + Object current = singletonFactory.getSingleton( + EzyBeanKey.of(beanName, method.getReturnType()) + ); if (current == null) { - EzySingletonLoader loader = new EzyByMethodSingletonLoader( + EzySingletonLoader loader = new EzyConfigurationMethodSingletonLoader( beanName, method, configurator, @@ -135,10 +150,12 @@ private void addPrototypeByField(EzyField field, Object configurator) { } private void addPrototypeByMethods(Object configurator) { - Map, EzyMethod> methods = mapPrototypeTypeMethods(); - Set> types = new HashSet<>(methods.keySet()); - for (Class type : types) { - addPrototypeByMethod(methods.remove(type), configurator); + Map methods = mapPrototypeKeyMethods(); + Set keys = new HashSet<>(methods.keySet()); + for (EzyBeanKey key : keys) { + EzyMethod method = methods.remove(key); + logger.debug("add prototype of {} with method {}", key, method); + addPrototypeByMethod(method, configurator); } } @@ -160,27 +177,32 @@ private List getSingletonFields() { return getBeanFields(EzySingleton.class); } - private Map, EzyMethod> mapSingletonTypeMethods() { - return mapBeanTypeMethods(EzySingleton.class); + private Map mapSingletonKeyMethods() { + return mapBeanKeyMethods(EzySingleton.class); } private List getPrototypeFields() { return getBeanFields(EzyPrototype.class); } - private Map, EzyMethod> mapPrototypeTypeMethods() { - return mapBeanTypeMethods(EzyPrototype.class); + private Map mapPrototypeKeyMethods() { + return mapBeanKeyMethods(EzyPrototype.class); } private List getBeanFields(Class annClass) { return clazz.getPublicFields(f -> f.isAnnotated(annClass)); } - @SuppressWarnings("unchecked") - private Map, EzyMethod> mapBeanTypeMethods(Class annClass) { + private Map mapBeanKeyMethods(Class annClass) { List methods = clazz.getPublicMethods(m -> m.isAnnotated(annClass) && m.getReturnType() != void.class ); - return EzyMaps.newHashMap(methods, EzyMethod::getReturnType); + return EzyMaps.newHashMap( + methods, + it -> EzyBeanKey.of( + getSingletonName(it), + it.getReturnType() + ) + ); } } diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleSingletonFactory.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleSingletonFactory.java index af139bbb..7fc3c116 100644 --- a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleSingletonFactory.java +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleSingletonFactory.java @@ -122,6 +122,11 @@ public Object getSingleton(String name, Class type) { return singleton; } + @Override + public Object getSingleton(EzyBeanKey key) { + return singletonByKey.get(key); + } + @Override public Object getSingleton(Map properties) { for (Entry entry : propertiesBySingleton.entrySet()) { diff --git a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleSingletonLoader.java b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleSingletonLoader.java index 0cc96c60..d7f8d832 100644 --- a/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleSingletonLoader.java +++ b/ezyfox-bean/src/main/java/com/tvd12/ezyfox/bean/impl/EzySimpleSingletonLoader.java @@ -90,7 +90,7 @@ private Object process(EzyBeanContext context) throws Exception { return answer; } - private Object getOrCreateSingleton( + protected Object getOrCreateSingleton( EzyBeanContext context, String name, Class[] parameterTypes diff --git a/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/testing/EzyBeanKeyTest.java b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/testing/EzyBeanKeyTest.java index 97a4e1f3..0924702d 100644 --- a/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/testing/EzyBeanKeyTest.java +++ b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/testing/EzyBeanKeyTest.java @@ -3,10 +3,25 @@ import com.tvd12.ezyfox.bean.impl.EzyBeanKey; import com.tvd12.test.assertion.Asserts; import com.tvd12.test.base.BaseTest; +import com.tvd12.test.performance.Performance; import org.testng.annotations.Test; public class EzyBeanKeyTest extends BaseTest { + public static void main(String[] args) { + EzyBeanKey hello = new EzyBeanKey("hello", String.class); + EzyBeanKey world = new EzyBeanKey("world", String.class); + long equalsTime = Performance.create() + .test(() -> hello.equals(world)) + .getTime(); + System.out.println("equalsTime: " + equalsTime); + + long hashCodeTime = Performance.create() + .test(hello::hashCode) + .getTime(); + System.out.println("hashCodeTime: " + hashCodeTime); + } + @Test public void test() { // given diff --git a/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/testing/EzyByMethodSingletonLoaderTest.java b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/testing/EzyByMethodSingletonLoaderTest.java index bd94c0bb..06441832 100644 --- a/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/testing/EzyByMethodSingletonLoaderTest.java +++ b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/testing/EzyByMethodSingletonLoaderTest.java @@ -28,7 +28,9 @@ public void test() throws Exception { EzyMethod methodB = new EzyMethod(getClass().getDeclaredMethod("newB")); EzyByMethodSingletonLoader loader = new EzyByMethodSingletonLoader( "a", - methodA, this, EzyMaps.newHashMap(B.class, methodB)); + methodA, + this, + EzyMaps.newHashMap(B.class, methodB)); Method getConstructorParameterTypes = EzyByMethodSingletonLoader.class .getDeclaredMethod("getConstructorParameterTypes", Class.class); diff --git a/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/V129DeclareTwoBeansSameTypeTest.java b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/V129DeclareTwoBeansSameTypeTest.java new file mode 100644 index 00000000..3125b768 --- /dev/null +++ b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/V129DeclareTwoBeansSameTypeTest.java @@ -0,0 +1,35 @@ +package com.tvd12.ezyfox.bean.v129.testing; + +import com.tvd12.ezyfox.bean.EzyBeanContext; +import com.tvd12.test.assertion.Asserts; +import org.testng.annotations.Test; + +public class V129DeclareTwoBeansSameTypeTest { + + @Test + public void test() { + // given + EzyBeanContext beanContext = EzyBeanContext.builder() + .scan("com.tvd12.ezyfox.bean.v129.testing.config") + .build(); + + // when + // then + Asserts.assertEquals( + beanContext.getBean("hello", String.class), + "hello" + ); + Asserts.assertEquals( + beanContext.getBean("world", String.class), + "world" + ); + Asserts.assertEquals( + beanContext.getBean("foo", String.class), + "foo" + ); + Asserts.assertEquals( + beanContext.getBean("bar", String.class), + "bar" + ); + } +} diff --git a/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/V129EzySimpleConfigurationLoaderTest.java b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/V129EzySimpleConfigurationLoaderTest.java new file mode 100644 index 00000000..461b5881 --- /dev/null +++ b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/V129EzySimpleConfigurationLoaderTest.java @@ -0,0 +1,58 @@ +package com.tvd12.ezyfox.bean.v129.testing; + +import com.tvd12.ezyfox.bean.EzySingletonFactory; +import com.tvd12.ezyfox.bean.impl.EzyBeanKey; +import com.tvd12.ezyfox.bean.impl.EzySimpleConfigurationLoader; +import com.tvd12.ezyfox.bean.v129.testing.config.V129BeanConfig; +import com.tvd12.ezyfox.reflect.EzyMethod; +import com.tvd12.ezyfox.util.EzyMapBuilder; +import com.tvd12.test.reflect.FieldUtil; +import com.tvd12.test.reflect.MethodInvoker; +import org.testng.annotations.Test; + +import static org.mockito.Mockito.*; + +public class V129EzySimpleConfigurationLoaderTest { + + @Test + public void addSingletonByMethodsMethodIsNullTest() throws Exception { + // given + EzySimpleConfigurationLoader instance = new EzySimpleConfigurationLoader(); + EzySingletonFactory singletonFactory = mock(EzySingletonFactory.class); + when( + singletonFactory.getSingleton(any(EzyBeanKey.class)) + ).thenReturn("foo"); + FieldUtil.setFieldValue(instance, "singletonFactory", singletonFactory); + + FieldUtil.setFieldValue( + instance, + "singletonMethodByKey", + EzyMapBuilder.mapBuilder() + .put( + EzyBeanKey.of("foo", String.class), + new EzyMethod( + V129BeanConfig.class.getDeclaredMethod("foo") + ) + ) + .put( + EzyBeanKey.of("bar", String.class), + null + ) + .toMap() + ); + V129BeanConfig config = new V129BeanConfig(); + + // when + MethodInvoker.create() + .object(instance) + .method("addSingletonByMethods") + .param(Object.class, config) + .invoke(); + + // then + verify(singletonFactory, times(1)).getSingleton( + any(EzyBeanKey.class) + ); + verifyNoMoreInteractions(singletonFactory); + } +} diff --git a/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/config/V129BeanConfig.java b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/config/V129BeanConfig.java new file mode 100644 index 00000000..9418b952 --- /dev/null +++ b/ezyfox-bean/src/test/java/com/tvd12/ezyfox/bean/v129/testing/config/V129BeanConfig.java @@ -0,0 +1,24 @@ +package com.tvd12.ezyfox.bean.v129.testing.config; + +import com.tvd12.ezyfox.bean.annotation.EzyConfigurationBefore; +import com.tvd12.ezyfox.bean.annotation.EzySingleton; + +@EzyConfigurationBefore +public class V129BeanConfig { + + @EzySingleton + public final String hello = "hello"; + + @EzySingleton + public final String world = "world"; + + @EzySingleton + public String foo() { + return "foo"; + } + + @EzySingleton + public String bar() { + return "bar"; + } +} diff --git a/ezyfox-bean/src/test/resources/AllTests.tng.xml b/ezyfox-bean/src/test/resources/AllTests.tng.xml index 1660f84e..317c0fa4 100644 --- a/ezyfox-bean/src/test/resources/AllTests.tng.xml +++ b/ezyfox-bean/src/test/resources/AllTests.tng.xml @@ -6,6 +6,7 @@ + diff --git a/ezyfox-msgpack/src/test/java/com/tvd12/ezyfox/codec/testing/MsgPackSimpleSerializerTest.java b/ezyfox-msgpack/src/test/java/com/tvd12/ezyfox/codec/testing/MsgPackSimpleSerializerTest.java index 48ad471e..76234ae0 100644 --- a/ezyfox-msgpack/src/test/java/com/tvd12/ezyfox/codec/testing/MsgPackSimpleSerializerTest.java +++ b/ezyfox-msgpack/src/test/java/com/tvd12/ezyfox/codec/testing/MsgPackSimpleSerializerTest.java @@ -28,7 +28,7 @@ public class MsgPackSimpleSerializerTest { public static void main(String[] args) { MsgPackSimpleSerializer serializer = new MsgPackSimpleSerializer(); - System.out.println((EzyPrints.printBytesToInts(serializer.serialize(-1)))); + System.out.println((EzyPrints.printBytesToInts(serializer.serialize("Hello World")))); } @Test