blob: ddbf554b3df437a666001a8c7c42114cb016530b [file] [log] [blame]
/*
* 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 java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class BeanUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtils.class);
public static final String DEFAULT_BEAN_CORE_RESOURCE = "classpath*:META-INF/spring/scb-core-bean.xml";
public static final String DEFAULT_BEAN_NORMAL_RESOURCE = "classpath*:META-INF/spring/*.bean.xml";
public static final String[] DEFAULT_BEAN_RESOURCE = new String[] {DEFAULT_BEAN_CORE_RESOURCE
, DEFAULT_BEAN_NORMAL_RESOURCE};
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() {
}
public static void init() {
init(DEFAULT_BEAN_RESOURCE);
}
public static void init(String... configLocations) {
prepareServiceCombScanPackage();
Set<String> locationSet = new LinkedHashSet<>();
addBeanLocation(locationSet, DEFAULT_BEAN_RESOURCE);
addBeanLocation(locationSet, configLocations);
context = new ClassPathXmlApplicationContext(locationSet.toArray(new String[0]));
}
public static void addBeanLocation(Set<String> locationSet, String... location) {
Arrays.stream(location).forEach(loc -> addBeanLocation(locationSet, loc));
}
public static void addBeanLocation(Set<String> locationSet, String location) {
if (location == null) {
return;
}
location = location.trim();
if (StringUtils.isNotEmpty(location)) {
locationSet.add(location);
}
}
private static void addItem(Set<String> set, String item) {
for (String it : set) {
if (item.startsWith(it)) {
return;
}
}
set.add(item);
}
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()) {
addItem(scanPackags, exist.trim());
}
}
}
// ensure servicecomb package exist
addItem(scanPackags, SCB_PACKAGE);
// add main class package
for (Class<?> mainClass : new Class<?>[] {JvmUtils.findMainClass(), JvmUtils.findMainClassByStackTrace()}) {
if (mainClass != null && mainClass.getPackage() != null) {
String pkg = mainClass.getPackage().getName();
addItem(scanPackags, pkg);
}
}
// finish
String scbScanPackages = StringUtils.join(scanPackags, ",");
System.setProperty(SCB_SCAN_PACKAGE, scbScanPackages);
LOGGER.info("Scb scan package list: " + scbScanPackages);
}
public static ApplicationContext getContext() {
return context;
}
public static void setContext(ApplicationContext applicationContext) {
context = applicationContext;
}
/**
* 不应该在业务流程中频繁调用,因为内部必然会加一个锁做互斥,会影响并发度
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) context.getBean(name);
}
public static <T> Map<String, T> getBeansOfType(Class<T> type) {
if (context == null) {
// for some test case
return Collections.emptyMap();
}
return context.getBeansOfType(type);
}
public static <T> T getBean(Class<T> type) {
if (context == null) {
// for some test case
return null;
}
return context.getBean(type);
}
/**
* Get the implemented class of the given instance
* @param bean the instance to get implemented class from
* @return the implemented class (if the checked class is proxied, return the ultimate target class)
* @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass
*/
public static Class<?> getImplClassFromBean(Object bean) {
return AopProxyUtils.ultimateTargetClass(bean);
}
public static <T extends SPIOrder & SPIEnabled> void addBeans(Class<T> cls, List<T> exists) {
if (context == null) {
return;
}
for (T instance : exists) {
context.getAutowireCapableBeanFactory().autowireBean(instance);
}
for (T bean : context.getBeansOfType(cls).values()) {
if (bean.enabled()) {
exists.add(bean);
}
}
exists.sort(Comparator.comparingInt(SPIOrder::getOrder));
}
}