[JAVA] Une histoire sur une BeanNotOfRequiredTypeException qui s'est produite après l'application d'AOP au printemps

Environnement d'exploitation

Comment l'exception s'est produite

Le code à l'origine de l'exception ne peut pas être publié, prenons donc à titre d'exemple l'application Todo introduite dans les directives TERASOLUNA: sweat:.

--Créez une classe qui implémente MethodInterceptor sous le package de domaine.

SampleInterceptor.java


package todo.domain.interceptor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SampleInterceptor implements MethodInterceptor {

  private static final Logger logger = LoggerFactory.getLogger(SampleInterceptor.class);

  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable {
    //Déconnectez-vous simplement avant d'exécuter la méthode cible
    logger.info("Interceptor called.");
    return invocation.proceed();
  }
}

--Appliquer ʻInterceptorcréé dans ↑ àTodoServiceImpl` dans le paramètre AOP dans todo-domain.xml.

todo-domain.xml


  <aop:config>
    <aop:pointcut id="sample" expression="execution(* todo.domain.service.todo.TodoServiceImpl.*(..))" />
    <aop:advisor advice-ref="resultMessagesLoggingInterceptor" pointcut="@within(org.springframework.stereotype.Service)" />← L'original
    <aop:advisor pointcut-ref="sample" advice-ref="sampleAdvice" order="-1" />
  </aop:config>

  <bean id="sampleAdvice" class="todo.domain.interceptor.SampleInterceptor" />

TodoController.java


@Controller
@RequestMapping("todo")
public class TodoController {
  @Inject
  TodoServiceImpl todoService;

Ainsi, lorsque j'exécute cette application Todo, j'obtiens l'exception suivante au démarrage.

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'todoServiceImpl' is expected to be of type 'todo.domain.service.todo.TodoServiceImpl' but was actually of type 'com.sun.proxy.$Proxy32'
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.checkBeanNotOfRequiredType(DefaultListableBeanFactory.java:1491)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.checkBeanNotOfRequiredType(DefaultListableBeanFactory.java:1498)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1470)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1102):rolling_eyes:
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
	... 42 more

Je suppose le type TodoServiceImpl, mais il semble qu'il soit en fait défini comme com.sun.proxy. $ Proxy32 type: scream:.

La raison en est la différence dans le mécanisme de création de proxy

Spring fournit deux mécanismes pour appliquer l'AOP.

  1. JDK DynamicProxy
  2. CGLib

Cette différence est due à Comprendre comment implémenter le traitement des requêtes courantes sur Spring MVC (+ Spring Boot). Il semble que vous implémentez une interface. Dans cet exemple, étant donné que l'interface est implémentée, elle a été convertie en Proxy en utilisant JDK DynamicProxy, mais il semble qu'une exception se soit produite parce que TodoContorller a essayé d'injecter la classe d'implémentation TodoServiceImpl. .. Dans ce cas, pour «injecter» la classe d'implémentation, il est nécessaire de la rendre Proxy en utilisant le mécanisme de CGLib, et le réglage est de définir l'attribut «proxy-target-class» de l'élément «config» d'AOP sur «true». Je vais. (La valeur par défaut est «false».)

todo-domain.xml


 <aop:config proxy-target-class="true">

Le paramètre ci-dessus force le mécanisme de conversion Proxy à être CGLib, et si la classe n'a pas à l'origine une interface, elle sera automatiquement convertie en Proxy par le mécanisme CGLib.

À propos, veuillez noter que Spring AOP ne s'applique pas aux classes qui ne sont pas enregistrées dans le conteneur DI **.

Comment en êtes-vous venu à publier cet article?

A noter car il s'est effectivement produit dans le système développé en entreprise: stuck_out_tongue:.

Autres articles / pages de référence

Recommended Posts

Une histoire sur une BeanNotOfRequiredTypeException qui s'est produite après l'application d'AOP au printemps
À propos de Spring AOP
À propos de Spring AOP
Une histoire sur un projet Spring Boot écrit en Java qui prend en charge Kotlin
Une histoire sur le JDK à l'ère de Java 11
A propos de Spring AOP Pointcut
Une histoire sur la prise en charge de la réplication par les applications Spring + Hibernate + MySQL
A propos de la liaison de l'annotation Spring AOP
Une petite histoire troublée avec Groovy
Créez un projet Spring Boot avec intellij et quittez immédiatement après le lancement
Une histoire sur la conversion des codes de caractères de UTF-8 en Shift-jis en Ruby
L'histoire de la rencontre d'un débordement arithmétique qui ne devrait pas être rencontré dans Ruby
A propos du renvoi d'une référence dans un Java Getter
[Création] Un mémorandum sur le codage en Java
L'histoire d'un super débutant participant pour la première fois au concours AtCoder (AtCoder Beginner Contest 140)