object is not an instance of dec…


 
package com.lrq.framework;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.lrq.annotation.Controller;
import com.lrq.annotation.RequestMapping;
import com.lrq.loader.MyClassLoader;

public class DispatcherServlet extends HttpServlet {
private Map<String, Object> beans = new ConcurrentHashMap<String, Object>();
// 射路径和方法的匹配;这个记得要去重复;
private Map<String, String> urlMapping = new ConcurrentHashMap<String, String>();

@Override
public void init() throws ServletException {
// 获取到字节 文件对象的路径,并找到对应的.class文件;
// 这需要用到递归的思想, 想啊, 怎么知道下面有没有路径呢?
String realPath = this.getServletContext().getRealPath(
"/WEB-INF/classes");
File file = new File(realPath);
try {
this.treeWalk(file);
} catch (Exception e) {
throw new RuntimeException(e);
}
}


private void treeWalk(File file) throws Exception {

if (file.isDirectory()) {
// 如果存在并且是一个目录,就获取该目录下的所有东东
File[] listFiles = file.listFiles();
for (File file2 : listFiles) {
treeWalk(file2);
}
} else {
if (file.exists()) {
// 判断是否是.class文件开头的;判断是否需要更 严谨;
if (file.getName().endsWith(".class")) {
// 创建文件读取流读取;
FileInputStream fileStream = new FileInputStream(file);
byte[] buf = new byte[1024];
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
int len = 0;
while ((len = fileStream.read(buf)) != -1) {
byteOut.write(buf, 0, len);
}

MyClassLoader loader = new MyClassLoader(this.getClass()
.getClassLoader());// 这个父类装载器,挂到装载器 上;
// 这个类 载器的双亲委托 载机制有关;
byte[] byteArray = byteOut.toByteArray();
Class<?> clazz = loader.loadClass(null, byteArray, 0,
byteArray.length);
Controller controller = clazz
.getAnnotation(Controller.class);
if (controller != null) {
beans.put(controller.value(), clazz.newInstance());
Method[] methods = clazz.getMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
RequestMapping requestMapping = method
.getAnnotation(RequestMapping.class);
if (requestMapping != null) {
// 匹配路径;
String value = requestMapping.value();
String actionMethod = clazz.getName() + "+"
+ method.getName();
urlMapping.put(value, actionMethod);
}
}
}

}
}

}
}

}

@SuppressWarnings({ "unchecked", "rawtypes" })
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 解析uri; heima/login.action
String uri = request.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/") + 1).replace(".do", "");
String urlValue = this.urlMapping.get(uri);
if (urlValue != null && urlValue.length() > 0) {
String[] urlValues = urlValue.split("[+]");
String className = urlValues[0];
String methodName = urlValues[1];
String simpleClassName = className.substring(className
.lastIndexOf(".") + 1);
try {
Class<?> forName = Class.forName(className);
Method method = forName.getMethod(methodName);
Object object=beans.get(simpleClassName);
Object invoke = method.invoke(object);
String result = (String) method.invoke(object);
request.getRequestDispatcher(result).forward(request, response);



} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

注意里面带颜色的代码:
1 我的Object object对象是由自定义的类装载器装载的;
2 class.forname对象是由tomcat服务器的webappclassloader进行加载的;
而我尝试着用webappclassloader的类装载器加载的字节码文件对象去获取他身上的method对象,然后调用method.invoke(object);
这个object对象是由另外一个类装载器装载的字节码文件对象创建的实例,这样肯定就会出问题;
这是我这个异常的根源
或者说一个字节码对象的唯一性有三部分确定:相同虚拟机+相同类加载器+相同的完整类名
<script type="text/javascript" id="wumiiRelatedItems"> </script>
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值