I have my own annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
}
And class:
package com.ltp.analog.test;
import com.ltp.analog.core.annotation.Component;
@Component
public class TestOne {
public void test(){
System.out.println("TEST ONE");
}
}
Also implemented custom ClassLoader:
package com.ltp.analog.reflection;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class AnalogClassLoader extends ClassLoader{
@Override
public Class findClass(String name) {
Class cl = findLoadedClass(name);
if(cl != null){
return cl;
}
byte[] b = loadClassFromFile(name);
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassFromFile(String fileName) {
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(
fileName.replaceAll("[.]", "/") + ".class");
byte[] buffer;
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
int nextValue = 0;
try {
while ( (nextValue = inputStream.read()) != -1 ) {
byteStream.write(nextValue);
}
} catch (IOException e) {
e.printStackTrace();
}
buffer = byteStream.toByteArray();
return buffer;
}
}
And ReflectionUtils
class which have to load all the classes in package recursively:
package com.ltp.analog.reflection;
import com.ltp.analog.Testing;
import com.ltp.analog.reflection.qualifier.ClassQualifier;
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
public class ReflectionUtils {
private static final AnalogClassLoader cl = new AnalogClassLoader();
public static List<Class> getClassesInPackageRecursively(String packName){
List<String> packs = getSubpackagesRecursively(packName);
List<Class> result = new LinkedList<>();
packs.forEach(pack -> result.addAll(getClassesInPackage(pack)));
return result.stream().distinct().collect(Collectors.toList());
}
public static List<Class> getClassesInPackage(String packName){
if(packName == null || packName.isEmpty()){
return List.of();
}
URL url = ClassLoader.getSystemClassLoader().getResource(packName.replaceAll("[.]", "/"));
if(url == null){
return List.of();
}
File pack = new File(url.getPath());
if(!pack.isDirectory() || pack.listFiles() == null){
return List.of();
}
return Arrays.stream(pack.listFiles())
.filter(File::isFile)
.filter(f -> f.getName().endsWith(".class"))
.map(f -> cl.findClass(packName + "." + f.getName().substring(0, f.getName().indexOf('.'))))
.collect(Collectors.toList());
}
public static List<String> getSubpackagesRecursively(String packName){
List<String> result = new LinkedList<>();
for(String pack : getSubpackages(packName)){
List<String> subPacks = getSubpackagesRecursively(pack);
result.addAll(subPacks);
}
result.add(packName);
return result.stream().distinct().collect(Collectors.toList());
}
public static List<String> getSubpackages(String packName){
if(packName == null || packName.isEmpty()){
return List.of();
}
URL url = ClassLoader.getSystemClassLoader().getResource(packName.replaceAll("[.]", "/"));
if(url == null){
return List.of();
}
File pack = new File(url.getPath());
if(!pack.isDirectory() || pack.listFiles() == null){
return List.of();
}
return Arrays.stream(pack.listFiles())
.filter(File::isDirectory)
.map(f -> packName + "." + f.getName())
.collect(Collectors.toList());
}
private ReflectionUtils(){}
}
The problem is that after loading all the classes in the passed package I'm trying to filter them and get only annotated by @Component
, but the result is weird:
someClass.isAnnotationPresent(Component.class)
returns false, even when there is a @Component
annotation in someClass.getDeclaredAnnotations()
Sample:
List<Class> componentClasses = new LinkedList<>();
scans.forEach(s -> componentClasses.addAll(ReflectionUtils.getClassesInPackageRecursively(s)));
System.out.printf("Classes: %d", componentClasses.size());
componentClasses.forEach(c -> {
System.out.println("-".repeat(50));
System.out.println(Arrays.stream(c.getAnnotations()).map(Annotation::toString).collect(Collectors.joining(", ")));
System.out.printf("%s -> %s\n", c.getName(), c.isAnnotationPresent(Component.class));
});
The output:
...
@com.ltp.analog.core.annotation.Component()
com.ltp.analog.test.TestOne -> false
...
Aucun commentaire:
Enregistrer un commentaire