Skip to content

Commit

Permalink
Merge pull request #416 from dinghuang/feature-handle-table
Browse files Browse the repository at this point in the history
[ADD] spring optimize
  • Loading branch information
xlorne authored Jul 2, 2020
2 parents bdfc60d + 021ebe4 commit 8b0e52f
Show file tree
Hide file tree
Showing 11 changed files with 408 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2011-2019, hubin ([email protected]).
* <p>
* Licensed 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 com.codingapi.txlcn.tc.annotation;

import java.lang.annotation.*;

/**
* @author [email protected]
* @since 2019/7/29
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TableId {

/**
* 字段值(驼峰命名方式,该值可无)
*/
String value() default "";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2011-2019, hubin ([email protected]).
* <p>
* Licensed 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 com.codingapi.txlcn.tc.annotation;

import java.lang.annotation.*;

/**
* @author [email protected]
* @since 2019/7/29
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableName {

/**
* 实体对应的表名
*/
String value() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,14 @@ private Map<String, Object> newKeyValues(List<Expression> expressions) {
Map<String, Object> keyValues = new HashMap<>();
for (int i = 0; i < columns.size(); i++) {
columns.get(i).setTable(table);
//解决Long类型字段作为主键空指针异常
if (primaryKeys.contains(columns.get(i).getFullyQualifiedName())) {
Object expression = expressions.get(i).getASTNode().jjtGetValue();
Object expression = null;
if (expressions.get(i).getASTNode() != null) {
expressions.get(i).getASTNode().jjtGetValue();
} else {
expression = expressions.get(i);
}
keyValues.put(columns.get(i).getFullyQualifiedName(),
Reflection.invokeN(expression.getClass(), "getValue", expression, new Object[0]));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.codingapi.txlcn.tc.core.transaction.txc.analy;

import com.codingapi.txlcn.tc.core.transaction.txc.analy.def.PrimaryKeysProvider;
import com.codingapi.txlcn.tc.core.transaction.txc.analy.util.AnnotationUtils;
import com.codingapi.txlcn.tc.core.transaction.txc.analy.util.ClassUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
* @author [email protected]
* @since 2019/7/28
*/
@Component
public class PrimaryKeyListVisitorHandler implements PrimaryKeysProvider {

@Value("${tx-lcn.primary-key-package}")
private String primaryKeyPackage;

@Override
public Map<String, List<String>> provide() {
if (primaryKeyPackage != null) {
//扫描所有注解,把主键拿进来
// 获取特定包下所有的类(包括接口和类)
List<Class<?>> clsList = ClassUtils.getClasses(primaryKeyPackage);
//输出所有使用了特定注解的类的注解值
return AnnotationUtils.getPrimaryKeyList(clsList);
} else {
return null;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.codingapi.txlcn.tc.core.transaction.txc.analy.util;

import com.codingapi.txlcn.tc.annotation.TableId;
import com.codingapi.txlcn.tc.annotation.TableName;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author [email protected]
* @since 2019/7/29
*/
public class AnnotationUtils {

private static Pattern humpPattern = Pattern.compile("[A-Z]");

public static Map<String, List<String>> getPrimaryKeyList(List<Class<?>> clsList) {
if (clsList != null && clsList.size() > 0) {
Map<String, List<String>> map = new HashMap<>(clsList.size());
for (Class<?> cls : clsList) {
//获取类中的所有的方法
boolean classHasAnnotation = cls.isAnnotationPresent(TableName.class);
if (classHasAnnotation) {
TableName tableName = cls.getAnnotation(TableName.class);
if (tableName.value().length() != 0) {
Field[] fields = cls.getDeclaredFields();
String tableIdVale = null;
for (Field field : fields) {
boolean fieldHasAnnotation = field.isAnnotationPresent(TableId.class);
if (fieldHasAnnotation) {
TableId tableId = field.getAnnotation(TableId.class);
//输出注解属性
if (tableId.value().length() != 0) {
tableIdVale = tableId.value();
} else {
//转驼峰
tableIdVale = humpToLine(field.getName());
}
break;
}
}
map.put(tableName.value(), Collections.singletonList(tableIdVale));
}
}
}
return map;
} else {
return null;
}
}

public static String humpToLine(String str) {
Matcher matcher = humpPattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
}
matcher.appendTail(sb);
return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.codingapi.txlcn.tc.core.transaction.txc.analy.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
* @author [email protected]
* @since 2019/7/29
*/
public class ClassUtils {

private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtils.class);

private static final String FILE = "file";
private static final String JAR = "jar";
private static final String CLASS_SIGN = ".class";

/**
* 从包package中获取所有的Class
*
* @param packageName packageName
* @return List
*/
public static List<Class<?>> getClasses(String packageName) {
List<Class<?>> classes = new ArrayList<>();
boolean recursive = true;
String packageDirName = packageName.replace('.', '/');
Enumeration<URL> dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (dirs.hasMoreElements()) {
URL url = dirs.nextElement();
String protocol = url.getProtocol();
if (FILE.equals(protocol)) {
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
} else if (JAR.equals(protocol)) {
JarFile jar;
try {
jar = ((JarURLConnection) url.openConnection()).getJarFile();
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (name.charAt(0) == '/') {
name = name.substring(1);
}
if (name.startsWith(packageDirName)) {
int idx = name.lastIndexOf('/');
if (idx != -1) {
packageName = name.substring(0, idx).replace('/', '.');
}
if (idx != -1) {
if (name.endsWith(CLASS_SIGN) && !entry.isDirectory()) {
// 去掉后面的".class" 获取真正的类名
String className = name.substring(packageName.length() + 1, name.length() - 6);
try {
classes.add(Class.forName(packageName + '.' + className));
} catch (ClassNotFoundException e) {
LOGGER.error(e.getMessage());
}
}
}
}
}
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
}
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
return classes;
}

/**
* 以文件的形式来获取包下的所有Class
*
* @param packageName packageName
* @param packagePath packagePath
* @param recursive recursive
* @param classes classes
*/
private static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, List<Class<?>> classes) {
File dir = new File(packagePath);
if (!dir.exists() || !dir.isDirectory()) {
return;
}
File[] dirFiles = dir.listFiles(file -> (recursive && file.isDirectory()) || (file.getName().endsWith(CLASS_SIGN)));
assert dirFiles != null;
for (File file : dirFiles) {
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);
} else {
String className = file.getName().substring(0, file.getName().length() - 6);
try {
classes.add(Class.forName(packageName + '.' + className));
} catch (ClassNotFoundException e) {
LOGGER.error(e.getMessage());
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.codingapi.txlcn.tracing;

import com.codingapi.txlcn.tracing.spring.TracingSpringContextUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

Expand All @@ -28,4 +30,8 @@
@ComponentScan
public class TracingAutoConfiguration {

@Bean
public TracingSpringContextUtils tracingSpringContextUtils() {
return new TracingSpringContextUtils();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import com.alibaba.fastjson.JSONObject;
import com.codingapi.txlcn.tracing.TracingContext;
import com.codingapi.txlcn.tracing.spring.SpringConfig;
import com.codingapi.txlcn.tracing.spring.TracingSpringContextUtils;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -57,7 +59,19 @@ public Server choose(Object key) {

// 1. 自己加入此事务组调用链
assert Objects.nonNull(registration);
TracingContext.tracing().addApp(registration.getServiceId(), registration.getHost() + ":" + registration.getPort());
//兼容springBoot 2.0以下版本
Boolean exitHost;
try {
exitHost = registration.getHost() != null;
} catch (NoSuchMethodError noSuchMethodError) {
exitHost = false;
}
if (!exitHost) {
SpringConfig springConfig = (SpringConfig) TracingSpringContextUtils.getContext().getBean("springConfig");
TracingContext.tracing().addApp(registration.getServiceId(), springConfig.getHost() + ":" + springConfig.getPort());
} else {
TracingContext.tracing().addApp(registration.getServiceId(), registration.getHost() + ":" + registration.getPort());
}

// 2. 获取所有要访问服务的实例
List<Server> servers = getLoadBalancer().getAllServers();
Expand Down
Loading

0 comments on commit 8b0e52f

Please sign in to comment.