Java根据包名获取指定接口的所有实现
2016-08-23 22:44
525 查看
原文出自:http://blog.csdn.net/anxpp/article/details/52295168,转载请注明出处,谢谢!
准备做一个IM,实现服务端的时候,准备将所有消息处理器(MessageHandler)使用责任链设计模式,但是又不希望增加处理器的时候修改责任链的实现。
这时想到了Spring框架的实现,我们在使用Spring Boot 时,只需要实现一些接口,Spring能自动处理。
所以就想到通过指定接口和要扫描的包路径来获取所有处理器接口的实现,这样动态添加处理器就不需要修改责任链的实现了。
具体代码如下:
package com.anxpp.im.config;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import com.anxpp.im.server.handler.MessageHandler;
/**
* 通过接口获取所有实现
*
* @author http://anxpp.com/ 时间:2016年8月23日 下午10:16:53
*/
@SuppressWarnings("rawtypes")
public class ClassUtil {
private Class clazz;
private String packagePath;
public ClassUtil(Class clazz, String packagePath) {
this.clazz = clazz;
this.packagePath = packagePath;
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
List<Class> handlers = new ClassUtil(MessageHandler.class, "com.anxpp.im.server.controller").getAllClassByPackage();
for (Class<MessageHandler> handler : handlers) {
handler.newInstance().dealMessage();
}
}
/**
* 通过包名获取所有实现(可以将包名配置到统一配置文件中)
*
* @param packageName
* @return
*/
@SuppressWarnings("unchecked")
public List<Class> getAllClassByPackage() {
ArrayList<Class> returnClassList = new ArrayList<Class>();
try {
List<Class> allClass = getClasses(packagePath);
// 判断是否是一个接口
for (int i = 0; i < allClass.size(); i++) {
if (clazz.isAssignableFrom(allClass.get(i))) {
if (!clazz.equals(allClass.get(i))) {
returnClassList.add(allClass.get(i));
}
}
}
} catch (Exception e) {
}
return returnClassList;
}
private List<Class> getClasses(String packageName) throws ClassNotFoundException, IOException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String path = packageName.replace(".", "/");
Enumeration<URL> resources = classLoader.getResources(path);
List<File> dirs = new ArrayList<File>();
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
dirs.add(new File(resource.getFile()));
}
ArrayList<Class> classes = new ArrayList<Class>();
for (File directory : dirs) {
classes.addAll((Collection<? extends Class>) findClass(directory, packageName));
}
return classes;
}
private List<Class> findClass(File directory, String packageName) throws ClassNotFoundException {
List<Class> classes = new ArrayList<Class>();
if (!directory.exists()) {
return classes;
}
File[] files = directory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
assert !file.getName().contains(".");
classes.addAll(findClass(file, packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
classes.add((Class) Class.forName(packageName + "." + file.getName().substring(0, file.getName().length() - 6)));
}
}
return classes;
}
}
处理器接口:
package com.anxpp.im.server.handler;
/**
* 客户端消息处理器接口
*
* @author http://anxpp.com/ 时间:2016年8月23日 下午8:18:05
*/
public interface MessageHandler {
void dealMessage();
}
其中一个处理器实现如下:
其中的@Handler注解还没用上,本意是判断接口同时判断是否注解为处理器。
准备做一个IM,实现服务端的时候,准备将所有消息处理器(MessageHandler)使用责任链设计模式,但是又不希望增加处理器的时候修改责任链的实现。
这时想到了Spring框架的实现,我们在使用Spring Boot 时,只需要实现一些接口,Spring能自动处理。
所以就想到通过指定接口和要扫描的包路径来获取所有处理器接口的实现,这样动态添加处理器就不需要修改责任链的实现了。
具体代码如下:
package com.anxpp.im.config;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import com.anxpp.im.server.handler.MessageHandler;
/**
* 通过接口获取所有实现
*
* @author http://anxpp.com/ 时间:2016年8月23日 下午10:16:53
*/
@SuppressWarnings("rawtypes")
public class ClassUtil {
private Class clazz;
private String packagePath;
public ClassUtil(Class clazz, String packagePath) {
this.clazz = clazz;
this.packagePath = packagePath;
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
List<Class> handlers = new ClassUtil(MessageHandler.class, "com.anxpp.im.server.controller").getAllClassByPackage();
for (Class<MessageHandler> handler : handlers) {
handler.newInstance().dealMessage();
}
}
/**
* 通过包名获取所有实现(可以将包名配置到统一配置文件中)
*
* @param packageName
* @return
*/
@SuppressWarnings("unchecked")
public List<Class> getAllClassByPackage() {
ArrayList<Class> returnClassList = new ArrayList<Class>();
try {
List<Class> allClass = getClasses(packagePath);
// 判断是否是一个接口
for (int i = 0; i < allClass.size(); i++) {
if (clazz.isAssignableFrom(allClass.get(i))) {
if (!clazz.equals(allClass.get(i))) {
returnClassList.add(allClass.get(i));
}
}
}
} catch (Exception e) {
}
return returnClassList;
}
private List<Class> getClasses(String packageName) throws ClassNotFoundException, IOException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String path = packageName.replace(".", "/");
Enumeration<URL> resources = classLoader.getResources(path);
List<File> dirs = new ArrayList<File>();
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
dirs.add(new File(resource.getFile()));
}
ArrayList<Class> classes = new ArrayList<Class>();
for (File directory : dirs) {
classes.addAll((Collection<? extends Class>) findClass(directory, packageName));
}
return classes;
}
private List<Class> findClass(File directory, String packageName) throws ClassNotFoundException {
List<Class> classes = new ArrayList<Class>();
if (!directory.exists()) {
return classes;
}
File[] files = directory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
assert !file.getName().contains(".");
classes.addAll(findClass(file, packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
classes.add((Class) Class.forName(packageName + "." + file.getName().substring(0, file.getName().length() - 6)));
}
}
return classes;
}
}
处理器接口:
package com.anxpp.im.server.handler;
/**
* 客户端消息处理器接口
*
* @author http://anxpp.com/ 时间:2016年8月23日 下午8:18:05
*/
public interface MessageHandler {
void dealMessage();
}
其中一个处理器实现如下:
package com.anxpp.im.server.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.anxpp.im.server.handler.Handler; import com.anxpp.im.server.handler.MessageHandler; @Handler public class LoginHandler implements MessageHandler{ private static final Logger log = LoggerFactory.getLogger(LoginHandler.class); @Override public void dealMessage() { log.info("登陆消息"); } }这里只是简单的实现,并没有完全贴出责任链的代码。
其中的@Handler注解还没用上,本意是判断接口同时判断是否注解为处理器。
相关文章推荐
- Java -- 获取指定接口的所有实现类或获取指定类的所有继承类
- JAVA-获取实现了指定接口类的所有实现类或继承了指定类的所有子类
- Java 实现获取指定文件夹下的指定格式的所有文件
- java中借助Spring获取所有带有指定注解的接口、类、对象
- java根据map指定的value值获取对应的key值使用Gson实现
- JAVA获取同一路径下所有子类或接口实现类
- C#获取C# DLL中的指定接口的所有实现实例
- Java动态获取某个接口下所有的实现类对象集合
- JAVA获取同一路径下所有子类或接口实现类
- JAVA获取同一路径下所有子类或接口实现类
- JAVA获取同一路径下所有子类或接口实现类
- java反射获取某接口的所有实现类
- (java)获取某文件夹下面所有的指定类型的文件名称,并根据情况返回可用的名称
- java中借助Spring获取所有带有指定注解的接口、类、对象-续集
- JAVA获取同一路径下所有子类或接口实现类
- Java动态获取某个接口下所有的实现类对象集合
- java中借助Spring获取所有带有指定注解的接口、类、对象
- Java 获取接口所有实现类
- 获取指定包名下继承或者实现某接口的所有类(扫描文件目录和所有jar)
- JAVA获取同一路径下所有子类或接口实现类