尝试在 Spring AOP 中使用目标切入点指示符时出错
Getting error when tried to use target pointcut designator in Spring AOP
我正在尝试 target 切入点指示符的简单示例 Spring AOP
但我不确定我在这里遗漏了什么。遇到以下错误。
BeanNotOfRequiredTypeException: Bean named 'fooDao' is expected to be
of type 'com.opensource.kms.FooDao' but was actually of type
'com.opensource.kms.$Proxy19'
FooDao Class
package com.opensource.kms;
import org.springframework.stereotype.Component;
interface BarDao {
String m();
}
@Component
public class FooDao implements BarDao {
public String m() {
System.out.println("implementation of m");
return "This is return value";
}
}
看点Class
package com.opensource.kms;
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 SecurityService {
@Pointcut("target(com.opensource.kms.FooDao)")
public void myPointCut() {}
@Before("myPointCut()")
public void beforeMethod() {
System.out.println("beforeMethod");
}
}
配置Class
package com.opensource.kms;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.opensource.kms")
public class JavaConfig {
}
MainApp Class
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
FooDao ob = ctx.getBean("fooDao", FooDao.class);
System.out.println("data -> "+ob.m());
ctx.close();
有人可以帮我解决这个问题,我不确定我需要在上面的代码中更新哪些步骤才能使用目标指示符。
Spring 默认使用 JDK 目标 class 动态代理。
在 Java 内部使用接口创建代理:
public class DebugProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new DebugProxy(obj));
}
private DebugProxy(Object obj) {
this.obj = obj;
}
}
这里obj是你的目标class == FooDao。它只有一个接口BarDao.
参考:https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html
对于您的 class FooDao 将基于接口 BarDao 创建代理实例,因为它是它拥有的唯一接口。
当你打电话给
FooDao ob = ctx.getBean("fooDao", FooDao.class);
由于aop代理,spring容器中不会有classFooDao的bean。 bean 的名称将相同,因为默认名称取自 class。但该对象将不再是 FooDao。它将是 spring 从您的接口 BarDao 创建的代理对象。
这就是为什么如果你改变 FooDao.class -> BarDao.class 一切都会好的:
BarDao ob = ctx.getBean("fooDao", BarDao.class);
我正在尝试 target 切入点指示符的简单示例 Spring AOP
但我不确定我在这里遗漏了什么。遇到以下错误。
BeanNotOfRequiredTypeException: Bean named 'fooDao' is expected to be of type 'com.opensource.kms.FooDao' but was actually of type 'com.opensource.kms.$Proxy19'
FooDao Class
package com.opensource.kms;
import org.springframework.stereotype.Component;
interface BarDao {
String m();
}
@Component
public class FooDao implements BarDao {
public String m() {
System.out.println("implementation of m");
return "This is return value";
}
}
看点Class
package com.opensource.kms;
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 SecurityService {
@Pointcut("target(com.opensource.kms.FooDao)")
public void myPointCut() {}
@Before("myPointCut()")
public void beforeMethod() {
System.out.println("beforeMethod");
}
}
配置Class
package com.opensource.kms;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.opensource.kms")
public class JavaConfig {
}
MainApp Class
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
FooDao ob = ctx.getBean("fooDao", FooDao.class);
System.out.println("data -> "+ob.m());
ctx.close();
有人可以帮我解决这个问题,我不确定我需要在上面的代码中更新哪些步骤才能使用目标指示符。
Spring 默认使用 JDK 目标 class 动态代理。
在 Java 内部使用接口创建代理:
public class DebugProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new DebugProxy(obj));
}
private DebugProxy(Object obj) {
this.obj = obj;
}
}
这里obj是你的目标class == FooDao。它只有一个接口BarDao.
参考:https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html
对于您的 class FooDao 将基于接口 BarDao 创建代理实例,因为它是它拥有的唯一接口。
当你打电话给
FooDao ob = ctx.getBean("fooDao", FooDao.class);
由于aop代理,spring容器中不会有classFooDao的bean。 bean 的名称将相同,因为默认名称取自 class。但该对象将不再是 FooDao。它将是 spring 从您的接口 BarDao 创建的代理对象。
这就是为什么如果你改变 FooDao.class -> BarDao.class 一切都会好的:
BarDao ob = ctx.getBean("fooDao", BarDao.class);