错误javax.servlet.ServletException: Servlet.init() for servlet com.hank.controller.UserLogin threw exception的解决:
背景 在写Spring的时候init()方法脑热写出来的错误: 浏览器错误提示: 错误日志: exception javax.servlet.ServletException: Servlet.init() for servlet com.hank.controller.UserLogin threw exception org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445) org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115) org.apache.coyote.AbstractProtocol
A
b
s
t
r
a
c
t
C
o
n
n
e
c
t
i
o
n
H
a
n
d
l
e
r
.
p
r
o
c
e
s
s
(
A
b
s
t
r
a
c
t
P
r
o
t
o
c
o
l
.
j
a
v
a
:
637
)
o
r
g
.
a
p
a
c
h
e
.
t
o
m
c
a
t
.
u
t
i
l
.
n
e
t
.
J
I
o
E
n
d
p
o
i
n
t
AbstractConnectionHandler.process(AbstractProtocol.java:637) org.apache.tomcat.util.net.JIoEndpoint
AbstractConnectionHandler.process(AbstractProtocol.java:637)org.apache.tomcat.util.net.JIoEndpointSocketProcessor.run(JIoEndpoint.java:318) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) java.util.concurrent.ThreadPoolExecutor
W
o
r
k
e
r
.
r
u
n
(
T
h
r
e
a
d
P
o
o
l
E
x
e
c
u
t
o
r
.
j
a
v
a
:
624
)
o
r
g
.
a
p
a
c
h
e
.
t
o
m
c
a
t
.
u
t
i
l
.
t
h
r
e
a
d
s
.
T
a
s
k
T
h
r
e
a
d
Worker.run(ThreadPoolExecutor.java:624) org.apache.tomcat.util.threads.TaskThread
Worker.run(ThreadPoolExecutor.java:624)org.apache.tomcat.util.threads.TaskThreadWrappingRunnable.run(TaskThread.java:61) java.lang.Thread.run(Thread.java:748) root cause
java.lang.ClassCastException: com.sun.proxy.Proxy127 cannot be cast to com.hank.service.Imp.UserServiceImp com.hank.controller.UserLogin.init(UserLogin.java:29) javax.servlet.GenericServlet.init(GenericServlet.java:158) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445) org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115) org.apache.coyote.AbstractProtocolAbstractConnectionHandler.process(AbstractProtocol.java:637) org.apache.tomcat.util.net.JIoEndpointSocketProcessor.run(JIoEndpoint.java:318) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) java.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:624) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.lang.Thread.run(Thread.java:748)
错误代码:
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
userService = (UserServiceImp) ac.getBean("userservice");
错误原因分析: 因为aop底层默认是jdk动态代理的方式,而jdk动态代理是基于接口来实现的。生成的代理对象和真实对象的关系是实现一样的方法接口的平级关系。对于平级之间的强转这是很显然是错误的。 解决方案1 把生成的代理对象修改为强转为接口使用接口来获得代理对象的引用。
private UserService userService;
@Override
public void init() throws ServletException {
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
userService = (UserService) ac.getBean("userservice");
解决方案2 开启aop的cglib动态代理方式:因为cglib动态代理是基于继承的方式来实现获得代理对象,因此获得代理对象和真实对象的关系是继承关系。因此可以强转。
开启步骤:
-
导入cglib的jar: . 2.在s’pring的配置开启cglib动态代理
<!-- 开启cjlib代理 基于继承-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
总结aop底层两种代理方式: 1、jdk动态代理 原理:jdk动态代理基于接口的代理方式,动态生成的代理对象和真实对象实现同一接口。调用JDK官方的类文件获取动态生产的代理对象。
public class Myjdk implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("扩展前");
Student student = new Student();
student.show();
System.out.println("扩展后");
return null;
}
}
MyInter myInter = (MyInter) Proxy.newProxyInstance(
test.class.getClassLoader(),
new Class[]{MyInter.class},
new Myjdk());
myInter.show();
2、cjlib动态代理 基于继承的方式来动态生成代理对象。需要导入cjlib 的jar,实现MethodInterceptor 接口
import net.sf.cglib.proxy.MethodInterceptor;
import java.lang.reflect.Method;
public class MyStudent implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable {
System.out.println("cglib代理前");
methodProxy.invokeSuper(o,objects);
System.out.println("cglib代理后");
return null;
}
}
Cglib调用:
import com.aop6_cglib.cglib.MyStudent;
import com.aop6_cglib.pojo.Student;
import net.sf.cglib.proxy.Enhancer;
public class test {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Student.class);
enhancer.setCallback(new MyStudent());
Student o = (Student) enhancer.create();
o.show();
}
}
博主温馨提示: 如果你想练习这个层实现,导包别导错了。 jdk上面案例代码的包路径: import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
cglib上面案例代码的包路径: import net.sf.cglib.proxy.MethodInterceptor; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer;
现在因为一些缘故,导致几个月说的Java日笔记总结不能按时发布。但是以后博主我以后会找时间补上javase的笔记。如果大家觉得有帮助就关注一下博主吧。
|