试图在Spring AOP中使用目标点标示符时得到错误信息

问题描述 投票:0回答:1

我正在尝试一个简单的例子 目标 点阵

但我不知道,我在这里缺少什么。面临以下错误。

BeanNotOfRequiredTypeException: 名为'fooDao'的Bean预期类型为'com.openource.kms.FooDao',但实际上类型为'com.openource.kms.$Proxy19'。

富道班

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";
    }
}

外观类

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");
    }
}

配置类

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类

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
FooDao ob = ctx.getBean("fooDao", FooDao.class);
System.out.println("data -> "+ob.m());
ctx.close();

谁能帮我一下,不知道上面的代码中我需要更新哪些步骤才能使用目标代号。

spring spring-aop
1个回答
3
投票

Spring默认为目标类使用JDK动态代理。

在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是你的目标类==FooDao。它只有一个接口BarDao。

参考文献 https:/docs.oracle.comjavase8docstechnotesguidesreflectionproxy.html。

对于你的类FooDao将基于BarDao接口创建代理实例,因为它是唯一的接口。

当你调用

FooDao ob = ctx.getBean("fooDao", FooDao.class);

由于使用了aop代理,spring容器中不会有FooDao类的bean。因为默认情况下,Bean的名字是取自类,所以名字是一样的。但是对象将不再是FooDao。它将是由你的接口BarDao创建的spring代理对象。

这就是为什么如果你把FooDao.class -> BarDao.class改为FooDao.class,一切都会好起来。

BarDao ob = ctx.getBean("fooDao", BarDao.class);

参考: https:/docs.spring.iospringdocscurrentspring-framework-referencecore.html#aop-understanding-aop-proxies。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.