La question est un peu théorique, quel est le coût de création de contexte JAXB, marshaller et unmarshaller?
J'ai trouvé que mon code pourrait bénéficier de garder le même contexte JAXB et peut-être le même marshaller pour toutes les opérations de marshaling plutôt que de créer un contexte et un marshaller à chaque marshaling.
Alors, quel est le coût de la création d'un contexte JAXB et d'un marshaller / unmarshaller? Est-il correct de créer context + marshaller pour chaque opération de marshaling ou mieux vaut l'éviter?
la source
Idéalement, vous devriez avoir un singleton
JAXBContext
et des instances locales deMarshaller
etUnmarshaller
.JAXBContext
les instances sont thread-safe tandisMarshaller
que lesUnmarshaller
instances ne sont pas thread-safe et ne doivent jamais être partagées entre les threads.la source
C'est dommage que cela ne soit pas spécifiquement décrit dans le javadoc. Ce que je peux dire, c'est que Spring utilise un JAXBContext global, partagé entre les threads, alors qu'il crée un nouveau marshaller pour chaque opération de marshalling, avec un commentaire javadoc dans le code indiquant que les marshallers JAXB ne sont pas nécessairement thread-safe.
La même chose est dite sur cette page: https://javaee.github.io/jaxb-v2/doc/user-guide/ch03.html#other-miscellaneous-topics-performance-and-thread-safety .
Je suppose que la création d'un JAXBContext est une opération coûteuse, car elle implique l'analyse des classes et des packages pour les annotations. Mais la mesurer est la meilleure façon de le savoir.
la source
JAXB 2.2 ( JSR-222 ) a ceci à dire, dans la section "4.2 JAXBContext":
Malheureusement, la spécification ne fait aucune déclaration concernant la sécurité des threads de
Unmarshaller
etMarshaller
. Il est donc préférable de supposer qu'ils ne le sont pas.la source
J'ai résolu ce problème en utilisant:
la source
Encore mieux!! En vous basant sur la bonne solution de l'article ci-dessus, créez le contexte une seule fois dans le constructeur et enregistrez-le à la place de la classe.
Remplacez la ligne:
avec celui-ci:
Et le constructeur principal avec celui-ci:
donc dans le getMarshaller / getUnmarshaller, vous pouvez supprimer cette ligne:
Cette amélioration fait, dans mon cas, que les temps de traitement passent de 60 ~ 70ms à seulement 5 ~ 10ms
la source
Je résous généralement des problèmes comme celui-ci avec un
ThreadLocal
modèle de classe. Étant donné que vous avez besoin d'un marshaller différent pour chaque classe, vous pouvez le combiner avec unsingleton
modèle -map.Pour vous faire gagner 15 minutes de travail. Voici mon implémentation d'une usine thread-safe pour Jaxb Marshallers et Unmarshallers.
Il vous permet d'accéder aux instances comme suit ...
Et le code dont vous aurez besoin est une petite classe Jaxb qui ressemble à ceci:
la source