【问题标题】:Seeing odd behavior when learning SpringAOP using @AspectJ style使用 @AspectJ 样式学习 SpringAOP 时看到奇怪的行为
【发布时间】:2013-12-16 18:13:15
【问题描述】:

我是 Spring Framework 的新手,我指的是 Spring 项目中可用的文档。

在这个过程中,我也在学习一个新概念 AOP。 我正在关注 spring 文档来尝试一些示例 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

我尝试使用 Spring AOP 为我的第一个 Aspect Helloworld 使用“@AspectJ”样式。

这是我的上下文配置文件

<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" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd">

     <aop:aspectj-autoproxy expose-proxy="false" />

    <context:annotation-config></context:annotation-config>

    <bean id="aoProgrammingAspectJ" class = "com.AOProgramming.AOProgrammingAspectJ">
    </bean>


    <bean id="aoProgrammingImpl" class = "com.AOProgramming.AOProgrammingImpl">
    </bean>

</beans>

这是一个简单的界面

package com.AOProgramming;

public interface AOProgrammingInterface {

    public void startAspecting();

}

我实现了这个接口

package com.AOProgramming;

public class AOProgrammingImpl implements AOProgrammingInterface {


    @Override
    public void startAspecting() {

        System.out.println("THe Aspecting has just begun for :");

    }
}

这是我为切入点和建议定义方面定义的地方

package com.AOProgramming;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;


@Aspect
public class AOProgrammingAspectJ {

    @Pointcut("execution( * com.AOProgramming.*.*(..))")
    public void cuttingOne() {}

    @Before("cuttingOne()")
    public void adviceCuttingOne1(){

        System.out.println("This is the at the beginning");

    }



}

这是我真正的 INVOKER 类

package com.AOProgramming;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AOProgrammingInvokerApp {

    public static void main(String[] args){

        ApplicationContext context = new ClassPathXmlApplicationContext("AOProgramming-servlet.xml");

        AOProgrammingImpl obj = (AOProgrammingImpl) context.getBean("aoProgrammingImpl");

        obj.startAspecting();

    }

}

当我尝试执行示例时,出现以下错误

Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy6 cannot be cast to com.AOProgramming.AOProgrammingImpl
    at com.AOProgramming.AOProgrammingInvokerApp.main(AOProgrammingInvokerApp.java:12)

我正在尝试重新阅读完整的页面,但我仍然遇到同样的问题,也没有获得足够的材料来处理最新的 Spring AOP 示例。所有早于 2002 年或 2008 年的 SpringAOP 都有不同的解释方式。

谁能帮我理解我在这里错过了什么

感谢您的帮助

【问题讨论】:

  • Spring bean(及其代理)的实际类型是 AOProgrammingInterface。这是从上下文中获取 bean 并使用它时应该使用的类型。
  • 感谢您的评论...

标签: spring aspectj spring-aop


【解决方案1】:

要理解这一点,您需要了解JDK proxies work and what their limitations are (and the alternative, CGLIB proxies) 的原理。简而言之,JDK 代理只保留目标 bean 接口的类型。所以为AOProgrammingImpl 生成的代理将是AOProgrammingInterface 类型,但不是AOProgrammingImpl,即使目标是AOProgrammingImpl 类型。

你可以改变这个

AOProgrammingImpl obj = (AOProgrammingImpl) context.getBean("aoProgrammingImpl");

到这里

AOProgrammingInterface obj = (AOProgrammingInterface) context.getBean("aoProgrammingImpl");

或者您可以将 CGLIB 添加到您的类路径并将您的配置更改为

<aop:aspectj-autoproxy expose-proxy="false" proxy-target-class="true" />

以便 Spring 使用与类类型一起使用的 CGLIB 代理。

【讨论】:

  • 感谢您的解释。现在对我来说,我在理解 AOP 的概念时错过了什么是有意义的。感谢分享有关代理的链接。老实说,很多学习...
  • @linux 这一切都会很快值得的 :)
  • 我有一个问题(如果它愚蠢,请原谅),如果我的类实现了两个接口怎么办?我应该把它投给哪个?
  • @linux 如果你的类实现了两个接口,那么代理也将实现这两​​个接口。您可以投射到任何您需要的位置。如果您需要调用FirstInterface 中声明的方法m1(),则需要将其转换为FirstInterface
  • 好的!!我问这个问题并没有真正考虑任何真正的用例,而是更多地了解代理。感谢您的澄清。
猜你喜欢
  • 2022-11-10
  • 2019-10-19
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 2020-09-05
  • 2021-03-27
  • 1970-01-01
相关资源
最近更新 更多