【问题标题】:class cast exception while initializing bean using ApplicationContext使用 ApplicationContext 初始化 bean 时发生类强制转换异常
【发布时间】:2017-04-30 19:23:25
【问题描述】:

我需要您的帮助来解决有关 Spring bean 初始化的问题。以下是问题的详细信息:

道接口

  package com.dao;

  import com.entity.Employee;

  public interface IEmployeeDao {

       Employee create(final Employee aEmployee);
       Employee fetchEmployeeById(final Integer aEmployeeId);
  }

dao 实现类

  package com.dao.impl;

  import javax.persistence.EntityManager;

  import com.dao.IEmployeeDao;
  import com.entity.Employee;

  public class EmployeeDao implements IEmployeeDao {

      private EntityManager em;

      @Override
      public Employee create(Employee aEmployee) {
           return this.em.merge(aEmployee);
      }

      @Override
      public Employee fetchEmployeeById(Integer aEmployeeId) {
         return this.em.find(Employee.class, aEmployeeId);
      }
  }

主类:

  package com.client;

  import java.sql.SQLException;

  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;

  import com.dao.impl.EmployeeDao;

  public class Client {
       private static final Logger LOGGER = LogManager.getLogger(Client.class);

       public static void main(String[] args) throws ClassNotFoundException, 
          SQLException {
       ApplicationContext applicationContext = new 
       ClassPathXmlApplicationContext(new String[] {"applicationcontext.xml"});
       LOGGER.info("client invoked");
       EmployeeDao employeeDao =  
         (EmployeeDao)applicationContext.getBean("employeeDao");    
       //....some code below
     }
   }

我试图获取employeeDao bean的代码的最后一行抛出以下异常:

  Exception in thread "main" java.lang.ClassCastException: 
  com.sun.proxy.$Proxy17 cannot be cast to 
  com.dao.impl.EmployeeDao
  at com.client.Client.main(Client.java:26)

根据我浏览的一些答案中的建议,我将上面的行更改为强制转换为接口而不是其实现类

    IEmployeeDao employeeDao =  
         (IEmployeeDao)applicationContext.getBean("employeeDao");

bean 被注入没有任何异常,但现在实际的实现方法没有被调用,即现在当我调用 EmployeedDao 的 create 方法时,如下所示

  employeeDao.create(new Employee());

创建方法的实现没有被调用,即下面的方法:

  @Override
  public Employee create(Employee aEmployee) {
       System.out.println("com.dao.impl.EmployeeDao.create(Employee) callled")
       return this.em.merge(aEmployee);
  }

我通过发送 sysout 消息确认了这一点。

请告诉我我做错了什么或者可以做些什么来摆脱这个问题。我还在下面发布了 bean 配置文件和 maven 依赖项。

applicationcontext.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ">
    <import resource="aspects.xml"/>
    <bean id="employeeDao" class="com.dao.impl.EmployeeDao" />

    </beans>

方面.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">

         <bean id="logAspect" 
               class="com.logging.LoggingAspect" />

         <aop:config>

            <aop:aspect id="aspectLoggging" ref="logAspect">
            <aop:pointcut id="pointCutAround"
                 expression="execution(* 
         com.dao.IEmployeeDao.*(..))" />

         aop:around method="logAround" pointcut-ref="pointCutAround" />

     </aop:aspect>
     </aop:config>
     </beans>

maven 依赖:

  <dependencies>
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>2.5.5</version>
     </dependency>
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>2.5.5</version>
     </dependency>
     <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.7.3</version>
     </dependency>
     <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.7.3</version>
     </dependency>      
     <dependency>
        <groupId>org.apache.derby</groupId>
        <artifactId>derby</artifactId>
        <version>10.13.1.1</version>
     </dependency>  
     <dependency>
       <groupId>org.hibernate</groupId>
       <artifactId>hibernate-entitymanager</artifactId>
       <version>3.6.0.Final</version>
     </dependency>
     <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.8.2</version>
     </dependency>
   </dependencies>

编辑:

LoggingAspect 类:

  package com.logging;

  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.aspectj.lang.JoinPoint;

  public class LoggingAspect {
       private static final Logger LOGGER = 
          LogManager.getLogger(LoggingAspect.class);
       public void logAround(JoinPoint aJoinPoint) {
               LOGGER.info("aspects logging enabled");
       }
 }

【问题讨论】:

  • "但是现在实际的实现方法没有被调用。"能说清楚点吗?
  • @davidxxx 我刚刚编辑了那部分,希望现在清楚了吗?
  • 您的错误是由在该 bean 上使用 AOP 引起的。尝试从 spring 配置中删除 aop xml 并运行初始版本的代码。此外,您使用的是非常旧的 spring-context 和 spring-aop 版本。我建议使用最新版本&lt;dependency&gt; &lt;groupId&gt;org.springframework&lt;/groupId&gt; &lt;artifactId&gt;spring-aop&lt;/artifactId&gt; &lt;version&gt;4.3.8.RELEASE&lt;/version&gt; &lt;/dependency&gt;
  • @IvanPronin 是的,我知道这个问题与 aop 的使用有关,我试过没有它,它就像你说的那样工作,但是我必须使用 aop 所以你能建议实际的问题是什么是以及如何处理它?
  • @IvanPronin 关于版本真的很重要吗?我的意思是我知道我应该使用最新版本,但您认为问题是因为旧版本引起的吗?

标签: java spring maven aop applicationcontext


【解决方案1】:

是的,您的 Aspect 有问题。它实际上并没有调用检测代码。试试这个:

public void logAround(ProceedingJoinPoint aJoinPoint) { // <<-- don't forget to change the type to ProceedingJoinPoint
  LOGGER.info("aspects logging enabled");
  aJoinPoint.proceed(); // this will continue to the instrumented code
}

【讨论】:

  • 非常感谢。它起作用了,我只花了一些时间将您的答案标记为已接受的答案,因为我正在研究为什么需要procectioningJoinPoint.proceed(),这很好了解它只需要围绕建议而不是其他建议类型。它也在 sring-aop 文档中提到,但可能我错过了阅读那部分。
猜你喜欢
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-12
  • 1970-01-01
  • 2016-12-12
相关资源
最近更新 更多