我找不到任何文档回答此问题。
总结:
- 我有一个实现接口的豆。
- 我将代理 - 目标类设置为false。
- i在Spring 3.2.17和4.3.3版本之间切换。
-
当我使用Spring 3.2.17时,主类抛出此:
java.lang.classcastException:com.sun.proxy。 com.package1.camera 在com.package1.app.main(app.java:8)
这就是我所期望的。这是正确的行为,因为生成了JDK代理类。
-
但是,当我使用弹簧4.3.3时,没有例外,主类也正确运行。
生成了CGLIB代理类。但是,当我将代理目标级设置为false时,为什么会生成?
这是源文件:
app.java
package com.package1;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Camera camera = (Camera) context.getBean("camera");
camera.snap();
context.close();
}
}
icamera.java
package com.package1;
public interface ICamera {}
camera.java
package com.package1;
import org.springframework.stereotype.Component;
@Component("camera")
public class Camera implements ICamera {
public void snap() {
System.out.println("SNAP!");
}
}
logger.java
package com.package1;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class Logger {
@Pointcut("execution(void com.package1.Camera.snap())")
public void cameraSnap() {
}
@Before("cameraSnap()")
public void beforeAdvice() {
System.out.println("Before advice...");
}
}
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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<context:component-scan
base-package="com.package1">
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
</beans>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.package1</groupId>
<artifactId>spring-test-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
</dependencies>
</project>
设置代理 - target-class = false时,CGLIB代理仍会使用相同的公式JDK代理创建。在春季文档中,他们说:
Spring AOP使用JDK Dynamic Proxies或CGLIB为给定目标对象创建代理。(每当您有选择时,JDK动态代理都是首选)。
如果要代理的目标对象至少一个接口,则将使用JDK动态代理。目标类型实现的所有接口将被代理。如果目标对象未实现任何接口,则将创建CGLIB代理。
请参阅更多:代理机制
通过反复试验和错误我提出了答案。
app.java
package com.package1;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Object o = context.getBean("camera");
System.out.println("class=" + o.getClass());
Camera camera = (Camera) context.getBean("camera");
camera.snap();
context.close();
}
}
代理 - 目标级仍然默认为false。
但是现在,春季4足够聪明,它将生成什么代理(JDK或CGLIB)。
- 如果您有一个空接口,它将生成一个CGLIB代理。
icamera.java
package com.package1;
public interface ICamera {}
- 否则,将生成JDK代理。
icamera.java
package com.package1;
public interface ICamera {
void snap();
}
hth。