这个问题困扰我很长时间,而且我两次跌倒在这个坑里,所以我决定把它记录下来(虽然它的改动很简单)
java.lang.NullPointerException
at gov.gfmis.fap.util.dao.springdao.GeneralDAO.getSession(GeneralDAO.java:59)
at gov.gfmis.fap.workflow.service.WorkFlowDesignImplBO.getBytes(WorkFlowDesignImplBO.java:328)
at gov.gfmis.fap.workflow.service.WorkFlowDesignImplBO.getWorkFlow(WorkFlowDesignImplBO.java:250)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:287)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.j
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:118
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
at $Proxy83.getWorkFlow(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:287)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.j
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.remoting.support.RemoteInvocationTraceInterceptor.invoke(RemoteInvocationTraceInterce
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
at $Proxy83.getWorkFlow(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:157)
at org.springframework.remoting.caucho.HessianServiceExporter.handleRequest(HessianServiceExporter.java:91)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:723)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:663)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:394)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:358)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
原来要代理的bean的配置:
<bean id="generalDAO" class="gov.gfmis.fap.util.dao.springdao.GeneralDAO">
<property name="sessionFactory" ref="mysessionFactory"/>
</bean>
GeneralDAO有这样的代码代码:
public final Session getSession() {
return getSession(this.hibernateTemplate.isAllowCreate());
}
private Session getSession(boolean allowCreate) {
return (!allowCreate ? SessionFactoryUtils.getSession(
getSessionFactory(), false) : SessionFactoryUtils.getSession(
getSessionFactory(), this.hibernateTemplate
.getEntityInterceptor(), this.hibernateTemplate
.getJdbcExceptionTranslator()));
}
public final void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = createHibernateTemplate(sessionFactory);
}
protected HibernateTemplate createHibernateTemplate(
SessionFactory sessionFactory) {
return new HibernateTemplate(sessionFactory);
}
public final void closeSession(Session s) {
try {
boolean existingTransaction = SessionFactoryUtils
.isSessionTransactional(s, getSessionFactory());
if (existingTransaction == false) {
SessionFactoryUtils.releaseSession(s, getSessionFactory());
}
} catch (HibernateException e) {
e.printStackTrace();
}
}
public final SessionFactory getSessionFactory() {
return (this.hibernateTemplate != null ? this.hibernateTemplate
.getSessionFactory() : null);
}
public final void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public final HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
加上代理的配置如下:
<bean id="generalDAOImpl" class="gov.gfmis.fap.util.dao.springdao.GeneralDAO">
<property name="sessionFactory" ref="mysessionFactory"/>
</bean>
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="generalDAO" >
<property name="target">
<ref bean="generalDAOImpl"/>
</property>
<property name="interceptorNames">
<list>
<value>aopMethod</value>
</list>
</property>
</bean>
<bean class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor" id="aopMethod" >
<property name="advice">
<bean class="gov.gfmis.epay.sql.interceptor.EPaySqlMethodBefore" />
</property>
<property name="mappedName">
<value>*</value>
</property>
</bean>
原来setSessionFactory、getSession()、getSessionFactory()、setHibernateTemplate方法都是final类型的。所以不能被继承的类重写。所以代理类实例化这个类的时候无法注入这些属性。
使用final的意思是不让重写这些方法,但是这些方法真的有必要被禁止重写,这个是按照spring代码的写法来写的。但是代码在没有变得像spring代码
那么精致之前,不应该不允许被重写,实际上final我觉得用的意义真不大,看不出来有什么作用。所以果断去掉就好了。
前人挖坑,后人填坑。这次记录下来这个坑是怎么造成的。