Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/pull_request_5x.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ jobs:
build:

runs-on: ubuntu-latest
services:
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- uses: actions/checkout@v1
Expand Down
37 changes: 36 additions & 1 deletion hsweb-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,29 @@
<name>${project.artifactId}</name>
<description>核心包</description>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.42</version>
</path>
<path>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>

<dependency>
Expand Down Expand Up @@ -168,11 +191,23 @@
<artifactId>hsweb-easy-orm-core</artifactId>
</dependency>

<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.8</version>
</dependency>

<dependency>
<groupId>io.micrometer</groupId>
<artifactId>context-propagation</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.37</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
</project>

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.hswebframework.web.bean;

import org.hswebframework.ezorm.core.Extendable;
import org.hswebframework.web.bean.accessor.AsmBeanAccessor;

import java.util.Map;

final class AsmAccessorFastBeanCopierBackend extends AccessorFastBeanCopierBackend {
private final AsmBeanAccessor asmBeanAccessor;

AsmAccessorFastBeanCopierBackend() {
this(new AsmBeanAccessor());
}

private AsmAccessorFastBeanCopierBackend(AsmBeanAccessor accessor) {
super(accessor);
this.asmBeanAccessor = accessor;
}

@Override
public Copier createCopier(Class<?> source, Class<?> target) {
if (!Map.class.isAssignableFrom(source)
&& !Map.class.isAssignableFrom(target)
&& !Extendable.class.isAssignableFrom(source)
&& !Extendable.class.isAssignableFrom(target)) {
Copier copier = asmBeanAccessor.createDirectCopier(source, target);
if (copier != null) {
return copier;
}
}
return super.createCopier(source, target);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class ClassDescription {
private final Class<?> type;

private final boolean collectionType;
private final boolean mapType;
private final boolean arrayType;
private final boolean enumType;
private final boolean enumDict;
Expand All @@ -23,24 +24,21 @@ public class ClassDescription {

public ClassDescription(Class<?> type) {
this.type = type;

collectionType = Collection.class.isAssignableFrom(type);
enumDict = EnumDict.class.isAssignableFrom(type);
arrayType = type.isArray();
enumType = type.isEnum();

number = Number.class.isAssignableFrom(type);
this.collectionType = Collection.class.isAssignableFrom(type);
this.mapType = Map.class.isAssignableFrom(type);
this.enumDict = EnumDict.class.isAssignableFrom(type);
this.arrayType = type.isArray();
this.enumType = type.isEnum();
this.number = Number.class.isAssignableFrom(type);
if (enumType) {
enums = type.getEnumConstants();
this.enums = type.getEnumConstants();
} else {
enums = null;
this.enums = null;
}
Map<String, Field> f = new HashMap<>();
ReflectionUtils.doWithFields(type, field -> {
f.put(field.getName(), field);
});
fields = Collections.unmodifiableMap(f);
fieldSize = fields.size();
Map<String, Field> fields = new HashMap<>();
ReflectionUtils.doWithFields(type, field -> fields.put(field.getName(), field));
this.fields = Collections.unmodifiableMap(fields);
this.fieldSize = this.fields.size();
}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package org.hswebframework.web.bean;


import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ClassDescriptions {

private static final Map<Class<?>, ClassDescription> CACHE = new ConcurrentHashMap<>();
private static final ClassLoaderScopedClassCache<ClassDescription> CACHE = new ClassLoaderScopedClassCache<>();

public static ClassDescription getDescription(Class<?> type) {
return CACHE.computeIfAbsent(type, ClassDescription::new);
}

static void clearCache() {
CACHE.clear();
}

static void clearCache(ClassLoader loader) {
CACHE.clear(loader);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.hswebframework.web.bean;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
* 按 classloader 分段的 Class 维度强缓存。
* <p>
* 普通稳定 classloader 直接走强缓存,动态 classloader 场景也保持强缓存命中,
* 通过 {@link #clear(ClassLoader)} 显式回收对应分段,避免弱/软引用在热路径上导致缓存重建。
*
* @param <V> value type
* @author zhouhao
* @since 5.0.2
*/
final class ClassLoaderScopedClassCache<V> {

private final Map<Class<?>, V> stableCache = new ConcurrentHashMap<>();
private final Map<ClassLoader, Map<Class<?>, V>> volatileCache = new ConcurrentHashMap<>();

V computeIfAbsent(Class<?> type, Function<Class<?>, V> mappingFunction) {
if (!FastBeanCopierSupport.isVolatileClassLoaderType(type)) {
return stableCache.computeIfAbsent(type, mappingFunction);
}
ClassLoader loader = FastBeanCopierSupport.getClassLoader(type);
return volatileCache
.computeIfAbsent(loader, ignore -> new ConcurrentHashMap<>())
.computeIfAbsent(type, mappingFunction);
}

void clear() {
stableCache.clear();
volatileCache.clear();
}

void clear(ClassLoader loader) {
if (loader == null) {
clear();
return;
}
stableCache.keySet().removeIf(type -> FastBeanCopierSupport.isClassLoaderMatch(type, loader));
volatileCache.remove(loader);
}
}
Loading
Loading