You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/06/21 11:22:59 UTC
[incubator-servicecomb-java-chassis] 04/04: [SCB-194] boot from
BeanUtils.init will auto scan main class package
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit 9147c70ac78f2dcd1d4e629da15eb51773234f73
Author: wujimin <wu...@huawei.com>
AuthorDate: Thu Jun 21 00:14:51 2018 +0800
[SCB-194] boot from BeanUtils.init will auto scan main class package
---
.../main/resources/META-INF/spring/cse.bean.xml | 2 +-
foundations/foundation-common/pom.xml | 19 +++--
.../foundation/common/utils/BeanUtils.java | 40 ++++++++++
.../foundation/common/utils/JvmUtils.java | 53 +++++++++++++
.../foundation/common/utils/TestBeanUtils.java | 90 ++++++++++++++++++++++
.../foundation/common/utils/TestJvmUtils.java | 71 +++++++++++++++++
6 files changed, 269 insertions(+), 6 deletions(-)
diff --git a/core/src/main/resources/META-INF/spring/cse.bean.xml b/core/src/main/resources/META-INF/spring/cse.bean.xml
index 44817fb..8ae429a 100644
--- a/core/src/main/resources/META-INF/spring/cse.bean.xml
+++ b/core/src/main/resources/META-INF/spring/cse.bean.xml
@@ -23,7 +23,7 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<!-- <context:spring-configured /> -->
- <context:component-scan base-package="org.apache.servicecomb"/>
+ <context:component-scan base-package="${scb-scan-package:org.apache.servicecomb}"/>
<bean class="org.apache.servicecomb.core.config.ConfigurationSpringInitializer">
<property name="configId" value="config"/>
diff --git a/foundations/foundation-common/pom.xml b/foundations/foundation-common/pom.xml
index d1a369f..dced02a 100644
--- a/foundations/foundation-common/pom.xml
+++ b/foundations/foundation-common/pom.xml
@@ -48,11 +48,6 @@
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
@@ -76,5 +71,19 @@
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb</groupId>
+ <artifactId>foundation-test-scaffolding</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java
index cb1536e..103ac79 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java
@@ -17,13 +17,22 @@
package org.apache.servicecomb.foundation.common.utils;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.TargetClassAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+
public final class BeanUtils {
public static final String DEFAULT_BEAN_RESOURCE = "classpath*:META-INF/spring/*.bean.xml";
+ public static final String SCB_SCAN_PACKAGE = "scb-scan-package";
+
+ private static final String SCB_PACKAGE = "org.apache.servicecomb";
+
private static ApplicationContext context;
private BeanUtils() {
@@ -33,10 +42,41 @@ public final class BeanUtils {
init(DEFAULT_BEAN_RESOURCE);
}
+
public static void init(String... configLocations) {
+ prepareServiceCombScanPackage();
+
context = new ClassPathXmlApplicationContext(configLocations);
}
+ public static void prepareServiceCombScanPackage() {
+ Set<String> scanPackags = new LinkedHashSet<>();
+ // add exists settings
+ String exists = System.getProperty(SCB_SCAN_PACKAGE);
+ if (exists != null) {
+ for (String exist : exists.trim().split(",")) {
+ if (!exist.isEmpty()) {
+ scanPackags.add(exist.trim());
+ }
+ }
+ }
+
+ // ensure servicecomb package exist
+ scanPackags.add(SCB_PACKAGE);
+
+ // add main class package
+ Class<?> mainClass = JvmUtils.findMainClass();
+ if (mainClass != null) {
+ String pkg = mainClass.getPackage().getName();
+ if (!pkg.startsWith(SCB_PACKAGE)) {
+ scanPackags.add(pkg);
+ }
+ }
+
+ // finish
+ System.setProperty(SCB_SCAN_PACKAGE, StringUtils.join(scanPackags, ","));
+ }
+
public static ApplicationContext getContext() {
return context;
}
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java
new file mode 100644
index 0000000..e2b2b86
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.common.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public final class JvmUtils {
+ private static final Logger LOGGER = LoggerFactory.getLogger(JvmUtils.class);
+
+ // available for oracle jdk/ open jdk, and maybe others
+ @VisibleForTesting
+ static final String SUN_JAVA_COMMAND = "sun.java.command";
+
+ private JvmUtils() {
+ }
+
+ /**
+ *
+ * @return main class or null, never throw exception
+ */
+ public static Class<?> findMainClass() {
+ String command = System.getProperty(SUN_JAVA_COMMAND);
+ if (command == null || command.isEmpty()) {
+ return null;
+ }
+
+ // command is main class and args
+ String mainClass = command.trim().split(" ")[0];
+ try {
+ return Class.forName(mainClass);
+ } catch (Throwable e) {
+ LOGGER.warn("\"{}\" is not a valid class.", mainClass, e);
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java
index fc7afcf..c9a28c1 100644
--- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java
+++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java
@@ -17,9 +17,15 @@
package org.apache.servicecomb.foundation.common.utils;
import org.aspectj.lang.annotation.Aspect;
+import org.junit.AfterClass;
import org.junit.Assert;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import mockit.Expectations;
+import mockit.Mocked;
public class TestBeanUtils {
static interface Intf {
@@ -34,6 +40,16 @@ public class TestBeanUtils {
static class MyAspect {
}
+ @BeforeClass
+ public static void setup() {
+ System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE);
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE);
+ }
+
@Test
public void test() {
Intf target = new Impl();
@@ -45,4 +61,78 @@ public class TestBeanUtils {
Assert.assertEquals(Impl.class, BeanUtils.getImplClassFromBean(proxy));
Assert.assertEquals(Impl.class, BeanUtils.getImplClassFromBean(new Impl()));
}
+
+ @Test
+ public void prepareServiceCombScanPackage_noExist_noMain() {
+ System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE);
+ new Expectations(JvmUtils.class) {
+ {
+ JvmUtils.findMainClass();
+ result = null;
+ }
+ };
+
+ BeanUtils.prepareServiceCombScanPackage();
+
+ Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE));
+ }
+
+ @Test
+ public void prepareServiceCombScanPackage_noExist_scbMain() {
+ System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE);
+ new Expectations(JvmUtils.class) {
+ {
+ JvmUtils.findMainClass();
+ result = TestBeanUtils.class;
+ }
+ };
+
+ BeanUtils.prepareServiceCombScanPackage();
+
+ Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE));
+ }
+
+ @Test
+ public void prepareServiceCombScanPackage_noExist_otherMain() {
+ System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE);
+ new Expectations(JvmUtils.class) {
+ {
+ JvmUtils.findMainClass();
+ result = String.class;
+ }
+ };
+
+ BeanUtils.prepareServiceCombScanPackage();
+
+ Assert.assertEquals("org.apache.servicecomb,java.lang", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE));
+ }
+
+ @Test
+ public void prepareServiceCombScanPackage_exist() {
+ System.setProperty(BeanUtils.SCB_SCAN_PACKAGE, "a.b,,c.d");
+ new Expectations(JvmUtils.class) {
+ {
+ JvmUtils.findMainClass();
+ result = null;
+ }
+ };
+
+ BeanUtils.prepareServiceCombScanPackage();
+
+ Assert.assertEquals("a.b,c.d,org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE));
+ }
+
+ @Test
+ public void init(@Mocked ClassPathXmlApplicationContext context) {
+ System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE);
+ new Expectations(JvmUtils.class) {
+ {
+ JvmUtils.findMainClass();
+ result = TestBeanUtils.class;
+ }
+ };
+ BeanUtils.init();
+
+ Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE));
+ }
}
diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java
new file mode 100644
index 0000000..d16792f
--- /dev/null
+++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.common.utils;
+
+import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestJvmUtils {
+ static String orgCmd = System.getProperty(JvmUtils.SUN_JAVA_COMMAND);
+
+ @Before
+ public void setup() {
+ System.clearProperty(JvmUtils.SUN_JAVA_COMMAND);
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ if (orgCmd == null) {
+ System.clearProperty(JvmUtils.SUN_JAVA_COMMAND);
+ return;
+ }
+
+ System.setProperty(JvmUtils.SUN_JAVA_COMMAND, orgCmd);
+ }
+
+ @Test
+ public void findMainClass_notExist() {
+ Assert.assertNull(JvmUtils.findMainClass());
+ }
+
+ @Test
+ public void findMainClass_existButEmpty() {
+ System.setProperty(JvmUtils.SUN_JAVA_COMMAND, "");
+ Assert.assertNull(JvmUtils.findMainClass());
+ }
+
+ @Test
+ public void findMainClass_invalid() {
+ LogCollector logCollector = new LogCollector();
+
+ System.setProperty(JvmUtils.SUN_JAVA_COMMAND, "invalidCls");
+
+ Assert.assertNull(JvmUtils.findMainClass());
+ Assert.assertEquals("\"invalidCls\" is not a valid class.", logCollector.getEvents().get(0).getMessage());
+ logCollector.teardown();
+ }
+
+ @Test
+ public void findMainClass_normal() {
+ System.setProperty(JvmUtils.SUN_JAVA_COMMAND, TestJvmUtils.class.getName() + " arg");
+
+ Assert.assertEquals(TestJvmUtils.class, JvmUtils.findMainClass());
+ }
+}