停止tomcat时使用spring服务获取java.io.NotSerializableException

停止tomcat时使用spring服务获取java.io.NotSerializableException,spring,jakarta-ee,spring-mvc,dependency-injection,inversion-of-control,Spring,Jakarta Ee,Spring Mvc,Dependency Injection,Inversion Of Control,我将Spring3与JSF2一起使用 我用SpringBean替换了JSF管理的bean,在bean之上添加了: @Component("mybean") @Scope("session") 在我的bean中,我正在自动连接一个spring服务(它是用注释@service声明的) 好吧,这项服务一切正常,但当我试图阻止Tomcat6时,我的spring服务出现了这个异常 java.io.NotSerializableException 你知道我为什么会遇到这个异常,以及如何解决它吗 更新:

我将Spring3与JSF2一起使用 我用SpringBean替换了JSF管理的bean,在bean之上添加了:

@Component("mybean")
@Scope("session")
在我的bean中,我正在自动连接一个spring服务(它是用注释@service声明的)

好吧,这项服务一切正常,但当我试图阻止Tomcat6时,我的spring服务出现了这个异常

java.io.NotSerializableException
你知道我为什么会遇到这个异常,以及如何解决它吗

更新:

在使我的服务实现可序列化后,有时会出现以下异常:

java.lang.IllegalStateException: Cannot deserialize BeanFactory with id org.springframework.web.context.WebApplicationContext:/spring_faces: no factory registered for this id
    at org.springframework.beans.factory.support.DefaultListableBeanFactory$SerializedBeanFactoryReference.readResolve(DefaultListableBeanFactory.java:972)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1061)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1762)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:480)
    at org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor.readObject(AbstractBeanFactoryPointcutAdvisor.java:98)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1667)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:480)
    at org.springframework.aop.framework.AdvisedSupport.readObject(AdvisedSupport.java:550)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
    at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1496)
    at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:998)
    at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:394)
    at org.apache.catalina.session.StandardManager.load(StandardManager.java:321)
    at org.apache.catalina.session.StandardManager.start(StandardManager.java:648)
    at org.apache.catalina.core.ContainerBase.setManager(ContainerBase.java:446)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4631)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
    at org.apache.catalina.core.StandardService.start(StandardService.java:525)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)

请告知。

您会遇到此异常,因为该类未实现
可序列化
。Tomcat将当前运行的
HttpSession
对象(包括其所有属性)序列化到磁盘,以便在重新启动/重新部署时,这些对象会在循环后恢复。会话范围的对象存储为
HttpSession
的属性,因此它们需要实现
Serializable
,以便在重新启动/重新部署后继续生存

如果要使它们可序列化,请相应地实施:

public class YourSpringService implements Serializable {}
否则,只需忽略异常或关闭Tomcat配置中的磁盘序列化会话


请注意,同样的情况也适用于JSF视图/会话范围的bean。

查看错误,tomcat似乎正在尝试序列化整个spring上下文,我认为这可能是由于您在服务上实现了Serializable。我在想也许你需要这样做,我对JSF不太了解,但我对作用域bean的理解让我想,你可能需要这样的东西

    @Component
    @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS, value="session")
    public class MyBean implements Serializable
    {
       //no need to implement serializable on service
       @Autowired(required=true)
       private MyService service;
    }

好吧,最后我能使它工作得很好,如下所示:

1-服务:

@Service
@Scope("singleton")
public class PersonService{

}
 @Component("person")
   @Scope("session")
   public class PersonBean implements Serializable{

   @Inject
   private PersonService personService;

   }
2-Spring管理的Bean:

@Service
@Scope("singleton")
public class PersonService{

}
 @Component("person")
   @Scope("session")
   public class PersonBean implements Serializable{

   @Inject
   private PersonService personService;

   }

等待您的反馈。

我不得不使用
readObject()
+
static ApplicationContext
hack来解决这个问题:

@Component
@Scope(value = SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class FlashMessages implements Serializable {    

    @Autowired
    transient private SomeBean someBean;

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
        // restore someBean field on deserialization
        SpringUtils.getContext().getAutowireCapableBeanFactory().autowireBean(this);
    }

}

@Component
public class SpringUtils implements ApplicationContextAware {

    static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    public static ApplicationContext getContext() {
        return applicationContext;
    }

}

所以问题是,我的SpringBean(jsf托管bean的替代品)是会话作用域并实现可序列化的,这个bean中使用的任何spring服务也必须实现可序列化的?如果您需要它们可序列化,那么是的。否则,将其标记为瞬态。我只是不保证Spring在恢复后会重新注入它们,这超出了我的知识范围(我不做Spring)。我认为问题在于@autowired of service,我认为如果您将服务设置为临时服务,那么服务将不会被序列化(因为您无法以任何方式真正序列化它,它只是一个prox)你们说的让服务暂时化是什么意思?@Jsword:use
transient
关键字。例如,
private transient Foo Foo Foo。这将跳过对属性的序列化。以下内容是什么意思proxyMode=ScopedProxyMode.TARGET_类,以及Autowiring中required=true的必要条件当我尝试此操作时,会出现异常:org.springframework.aop.framework.aopconfigeException:无法代理目标类,因为CGLIB2不可用。将CGLIB添加到类路径或指定代理接口。您不需要required is true(只是指示容器此依赖项不能忽略)。默认情况下,您需要此依赖项CGLIB cglib2.2.2,如果将CGLIB放入类路径中,您可以使用JDK或CGLIB创建代理。spring使用CGLIB创建prxoy。好的,我会试试,但您没有告诉我代码的意思:proxyMode=ScopedProxyMode.TARGET\u CLASSRead这一节3.4.4.5。从下面的文档中