前言
怎麼進一步用反射,在BeanFactoryPostProcessor 做做文章
## 調用
public void testRpcRouter(String methodTyep,String typeCode) throws Exception {
DemoDO demoDO = new DemoDO();
AbstractHandler abstractHandler = handlerContext.getInstance(typeCode);
abstractHandler.rpc(demoDO);
Method method = handlerContext.getMethodInstance(methodTyep);
method.invoke(new MethodList(), demoDO);
}
加載
@Component
public class HandlerProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
Map<String, Class> map = Maps.newHashMapWithExpectedSize(2);
Map<String, Method> methodMap = Maps.newHashMapWithExpectedSize(2);
List<Class<?>> scan =AnnotationScannerUtils.scan("com.domain.cls", HandlerType.class);
for (Class<?> clazz : scan) {
String type = ((HandlerType) clazz.getAnnotation(HandlerType.class)).value();
map.put(type, clazz);
}
List<Method> methods =AnnotationScannerUtils.scanMethodByAnnotation(MethodList.class, MethodType.class);
for (Method item : methods) {
String type = ((MethodType) item.getAnnotation(MethodType.class)).value();
methodMap.put(type, item);
}
configurableListableBeanFactory.registerResolvableDependency(HandlerContext.class, new HandlerContext(map, methodMap));
}
}
自定義的註解
@Documented
@Inherited
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodType {
String value();
}
@Documented
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface HandlerType {
String value();
}
容器
public class HandlerContext {
private Map<String, Class> map;
private Map<String, Method> methodMap;
public HandlerContext(Map<String, Class> map, Map<String, Method> methodMap) {
this.map = map;
this.methodMap = methodMap;
}
public AbstractHandler getInstance(String type) {
Class c = map.get(type);
return ( AbstractHandler) SpringFactoryUtil.getBean(c);
}
public Method getMethodInstance(String type) {
Method c = methodMap.get(type);
return c;
}
}
掃描
package com.ly.fn.xxd.srv.domain;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
public class AnnotationScannerUtils {
private static final Logger logger = LoggerFactory.getLogger(com.ly.fn.xxd.srv.domain.AnnotationScannerUtils.class);
private static final String EXT = "class";
private static final String PROJECT_PATH = System.getProperty("user.dir");
private static String packAge = com.ly.fn.xxd.srv.domain.AnnotationScannerUtils.class.getPackage().getName();
private static final String PACKAGE = packAge.substring(0, packAge.lastIndexOf("."));
private static String packageConvertPath(String packageName) {
return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName);
}
public static String getPkgPath(String pkgName) {
String pkgDirName = pkgName.replaceAll("\\.", "/");
URL url = Thread.currentThread().getContextClassLoader().getResource(pkgDirName);
return url == null ? null : url.getFile();
}
public static List<Class<?>> scan(String pkgName, Class<? extends Annotation> Annotation) {
Set<Class<?>> set = scanClasses(pkgName, getPkgPath(pkgName), false);
List<Class<?>> result = new ArrayList<>();
for (Class<?> aClass : set) {
if (aClass.isAnnotationPresent(Annotation)) {
result.add(aClass);
}
}
return result;
}
public static Set<Class<?>> scanClasses(String pkgName, String pkgPath, final boolean recursive) {
Set<Class<?>> classesSet = new HashSet<>();
Collection<File> allClassFile = getAllClassFile(pkgPath, recursive);
for (File curFile : allClassFile) {
try {
classesSet.add(getClassObj(curFile, pkgPath, pkgName));
} catch (ClassNotFoundException e) {
logger.error("load class fail", e);
}
}
return classesSet;
}
public static Map<Class<? extends Annotation>, Set<Class<?>>> scanClassesByAnnotations(
String pkgName, String pkgPath, final boolean recursive, List<Class<? extends Annotation>> targetAnnotations) {
Map<Class<? extends Annotation>, Set<Class<?>>> resultMap = new HashMap<>(16);
Collection<File> allClassFile = getAllClassFile(pkgPath, recursive);
for (File curFile : allClassFile) {
try {
Class<?> curClass = getClassObj(curFile, pkgPath, pkgName);
for (Class<? extends Annotation> annotation : targetAnnotations) {
if (curClass.isAnnotationPresent(annotation)) {
if (!resultMap.containsKey(annotation)) {
resultMap.put(annotation, new HashSet<Class<?>>());
}
resultMap.get(annotation).add(curClass);
}
}
} catch (ClassNotFoundException e) {
logger.error("load class fail", e);
}
}
return resultMap;
}
private static Class<?> getClassObj(File file, String pkgPath, String pkgName) throws ClassNotFoundException {
String absPath = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - EXT.length() - 1);
String className = absPath.substring(pkgPath.length()).replace(File.separatorChar, '.');
className = className.startsWith(".") ? pkgName + className : pkgName + "." + className;
return Thread.currentThread().getContextClassLoader().loadClass(className);
}
private static Collection<File> getAllClassFile(String pkgPath, boolean recursive) {
File fPkgDir = new File(pkgPath);
if (!(fPkgDir.exists() && fPkgDir.isDirectory())) {
logger.error("the directory to package is empty: {}", pkgPath);
return null;
}
return FileUtils.listFiles(fPkgDir, new String[]{EXT}, recursive);
}
public static List<Method> scanMethodByAnnotation(Class<?> classes, Class<? extends Annotation> annotation) {
List<Method> list = new ArrayList<>();
Method[] methods = classes.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(annotation)) {
list.add(method);
}
}
return list;
}
public static Map<Class<? extends Annotation>, Set<Method>> scanMethodsByAnnotations(Set<Class<?>> classes,
List<Class<? extends Annotation>> targetAnnotations) {
Map<Class<? extends Annotation>, Set<Method>> resultMap = new HashMap<>(16);
for (Class<?> cls : classes) {
Method[] methods = cls.getMethods();
for (Class<? extends Annotation> annotation : targetAnnotations) {
for (Method method : methods) {
if (method.isAnnotationPresent(annotation)) {
if (!resultMap.containsKey(annotation)) {
resultMap.put(annotation, new HashSet<Method>());
}
resultMap.get(annotation).add(method);
}
}
}
}
return resultMap;
}
}
具體實現類
類級別
整體