线程 "main" java.lang.ClassCastException 中的异常:com.sun.proxy.$Proxy13 无法转换为 CustomeClass
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy13 cannot be cast to CustomeClass
我正在尝试使用 Spring 框架学习 AOP,但有一个异常一直被调用。
Error : Exception in thread "main" java.lang.ClassCastException:
com.sun.proxy.$Proxy13 cannot be cast to com.controller.Triangle
Shape.java
package com.controller;
public interface Shape {
public void draw();
}
Triangle.java
package com.controller;
import org.springframework.stereotype.Component;
@Component
public class Triangle implements Shape
{
public void draw()
{
System.out.println("this draw method of triangle"),
}
}
myCustomAspect.java
package com.AOP;
import org.aspectj.lang.annotation.After;
@EnableAspectJAutoProxy
@Component
@Aspect
public class myCustomAspect {
@Pointcut("execution(* *.draw())")
private void pop(){}
@Before("pop()")
private void beforeMeth(){
System.out.println("this is before draw"); }
}
在主要方法中
ApplicationContext ssp = new ClassPathXmlApplicationContext("/Spring.xml");
Shape tr=(Triangle)ssp.getBean("triangle");
tr.draw();
Spring.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:context="http://www.springframework.org/schema/context"
xmlns:aop = "http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.controller,com.AOP"></context:component-scan>
</beans>
请任何人帮助。
感谢 MCVE,现在很容易重现您的问题并验证修复。只是阅读代码但无法 运行 它并没有让我发现问题。
很简单:您的建议beforeMeth()
必须public。然后一切都像魅力一样。
更新:
好的,我想我知道你缺少什么。您正在将创建的 bean 转换为 Triangle
,但这不是一个接口而是一个 class,因此如果没有进一步的配置,它不能被 Spring AOP 代理。所以你在这里有两个选择:
或者您只需将代码更改为 Shape tr = (Shape) appContext.getBean("triangle");
以便转换为 Spring 自动使用的接口,以便创建 JDK 动态代理.
或者您启用 class 通过 <aop:aspectj-autoproxy proxy-target-class="true"/>
使用 CBLIB 代理。当然,您也可以使用 @EnableAspectJAutoProxy(proxyTargetClass = true)
。
现在这是一个并行显示两种方法的解决方案。可以通过改变XML_CONFIG
.
的值来切换
顺便说一句,我还将您的包名称 com.AOP
更正为 com.aop
(小写字符是包的默认字符),并将您的 Aspect 名称从 myCustomAspect
更正为 MyCustomAspect
(Java classes 应以大写字符开头)。我还将 Spring.xml
重命名为 spring.xml
。在接口中,您不需要 public
来进行方法声明,因为所有接口方法的定义都是 public。但所有这些都只是表面功夫,真正的解决办法是上面那个。
这是您改进后的代码:
package com.controller;
public interface Shape {
void draw();
}
package com.controller;
import org.springframework.stereotype.Component;
@Component
public class Triangle implements Shape {
public void draw() {
System.out.println("this draw method of triangle");
}
}
package com.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyCustomAspect {
@Pointcut("execution(* *.draw())")
private void pop() {}
@Before("pop()")
public void beforeMeth() {
System.out.println("this is before draw");
}
}
package de.scrum_master.app;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.controller.Shape;
import com.controller.Triangle;
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ComponentScan(basePackages = { "com.controller", "com.aop" })
public class Application {
private static final boolean XML_CONFIG = true;
public static void main(String[] args) {
ApplicationContext appContext = XML_CONFIG
? new ClassPathXmlApplicationContext("/spring.xml")
: new AnnotationConfigApplicationContext(Application.class);
Shape tr = (Triangle) appContext.getBean("triangle");
tr.draw();
}
}
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
<context:component-scan base-package="com.controller,com.aop"></context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
我正在尝试使用 Spring 框架学习 AOP,但有一个异常一直被调用。
Error : Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy13 cannot be cast to com.controller.Triangle
Shape.java
package com.controller;
public interface Shape {
public void draw();
}
Triangle.java
package com.controller;
import org.springframework.stereotype.Component;
@Component
public class Triangle implements Shape
{
public void draw()
{
System.out.println("this draw method of triangle"),
}
}
myCustomAspect.java
package com.AOP;
import org.aspectj.lang.annotation.After;
@EnableAspectJAutoProxy
@Component
@Aspect
public class myCustomAspect {
@Pointcut("execution(* *.draw())")
private void pop(){}
@Before("pop()")
private void beforeMeth(){
System.out.println("this is before draw"); }
}
在主要方法中
ApplicationContext ssp = new ClassPathXmlApplicationContext("/Spring.xml");
Shape tr=(Triangle)ssp.getBean("triangle");
tr.draw();
Spring.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:context="http://www.springframework.org/schema/context"
xmlns:aop = "http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.controller,com.AOP"></context:component-scan>
</beans>
请任何人帮助。
感谢 MCVE,现在很容易重现您的问题并验证修复。只是阅读代码但无法 运行 它并没有让我发现问题。
很简单:您的建议beforeMeth()
必须public。然后一切都像魅力一样。
更新:
好的,我想我知道你缺少什么。您正在将创建的 bean 转换为 Triangle
,但这不是一个接口而是一个 class,因此如果没有进一步的配置,它不能被 Spring AOP 代理。所以你在这里有两个选择:
或者您只需将代码更改为
Shape tr = (Shape) appContext.getBean("triangle");
以便转换为 Spring 自动使用的接口,以便创建 JDK 动态代理.或者您启用 class 通过
<aop:aspectj-autoproxy proxy-target-class="true"/>
使用 CBLIB 代理。当然,您也可以使用@EnableAspectJAutoProxy(proxyTargetClass = true)
。
现在这是一个并行显示两种方法的解决方案。可以通过改变XML_CONFIG
.
顺便说一句,我还将您的包名称 com.AOP
更正为 com.aop
(小写字符是包的默认字符),并将您的 Aspect 名称从 myCustomAspect
更正为 MyCustomAspect
(Java classes 应以大写字符开头)。我还将 Spring.xml
重命名为 spring.xml
。在接口中,您不需要 public
来进行方法声明,因为所有接口方法的定义都是 public。但所有这些都只是表面功夫,真正的解决办法是上面那个。
这是您改进后的代码:
package com.controller;
public interface Shape {
void draw();
}
package com.controller;
import org.springframework.stereotype.Component;
@Component
public class Triangle implements Shape {
public void draw() {
System.out.println("this draw method of triangle");
}
}
package com.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyCustomAspect {
@Pointcut("execution(* *.draw())")
private void pop() {}
@Before("pop()")
public void beforeMeth() {
System.out.println("this is before draw");
}
}
package de.scrum_master.app;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.controller.Shape;
import com.controller.Triangle;
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ComponentScan(basePackages = { "com.controller", "com.aop" })
public class Application {
private static final boolean XML_CONFIG = true;
public static void main(String[] args) {
ApplicationContext appContext = XML_CONFIG
? new ClassPathXmlApplicationContext("/spring.xml")
: new AnnotationConfigApplicationContext(Application.class);
Shape tr = (Triangle) appContext.getBean("triangle");
tr.draw();
}
}
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
<context:component-scan base-package="com.controller,com.aop"></context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>