为什么我用 toString() 得到相同的结果而用 getClass().getName() 得到不同的结果

Why do I get same result with toString() but different result with getClass().getName()

我正在学习AOP,在spring项目中,有如下一段代码

MainDemoApp.java

public class MainDemoApp {

    public static void main(String[] args) {

        // read spring config java class
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(DemoConfig.class);

        // DemoConfig.class is a simple class with just component scanning enabled 
        // and with @EnableAspectJAutoProxy

        // get the bean from spring container
        AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);

        System.out.println(accountDAO.toString()); // line to be modified

        // call the business method
        accountDAO.addAccount();

        // close the context
        context.close();
    }
}

AccountDAO.java

@Component
public class AccountDAO {
    public void addAccount() {
        System.out.println(this.toString()); // line to be modified
    }
}

还有我的方面class MyDemoLoggingAspect.java

@Aspect
@Component
public class MyDemoLoggingAspect {

    // this is where we add all our related advices for logging

    // let's start with a @Before advice
    @Before("execution(public void addAccount())")
    public void beforeAddAccountAdvice() {
        System.out.println("\n=======>>> Executing @Before Advice");
    }
}

现在,当我在 MainDemoApp 中使用 运行 main 方法时,我得到以下输出- 输出-

com.luv2code.aopdemo.dao.AccountDAO@3e0e1046

=======>>> Executing @Before Advice
com.luv2code.aopdemo.dao.AccountDAO@3e0e1046

正如你所看到的线条

System.out.println(accountDAO.toString());

System.out.println(this.toString());

给出同样的结果,before advice也执行成功。 默认情况下 toString() 定义为-

this.getClass().getName() + "@" + Integer.toHexString(this.hashCode())

但是当我显式打印出 getClass().getName() 时,结果不同

System.out.println(accountDAO.getClass().getName());

System.out.println(this.getClass().getName());

输出-

com.luv2code.aopdemo.dao.AccountDAO$$EnhancerBySpringCGLIB$eb61b6

=======>>> Executing @Before Advice
com.luv2code.aopdemo.dao.AccountDAO

两个class名字都不一样,不知道是哪种class名字。 此外,当我显式打印 hashCode() 时,结果也不同。

我对得到不同的结果感到困惑-

  1. toString(),当 toString() 包括 getClass().getName()hashCode()
  2. getClass().getName()
  3. hashCode()

为什么会有这些差异,我没有覆盖任何这些方法(在我这边),这是否与 AOP 代理有关?

请帮我解开这些疑惑。

编辑- 我也有一个非常奇怪的观察,当我修改 MainDemoApp.java

AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);

System.out.println(accountDAO.hashCode());
// call the business method
accountDAO.addAccount(accountDAO);

AccountDAO.java修改为-

public void addAccount(AccountDAO obj) {
        System.out.println(this.hashCode() + " " + obj.hashCode());
}

现在 hashCode() 的结果是一样的,但是如果我不更改方法签名并在前一段代码上调用 hashCode(),结果就不同了

谁也能解释一下吗?

欢迎来到 SO。请注意,在此平台上,最好只提出一个明确的问题,而不是提出很多问题。但我们也尽量对新手友善,所以我试着回答你的问题。虽然这有点多余,因为其他人已经在评论中回复了,但我也认为评论是评论,答案是答案,即答案应该这样写。可能这里的其他贡献者太忙了,无法写出全面的答案,所以我在这里接球。

System.out.println(accountDAO.toString());

And

System.out.println(this.toString());

give the same result

这是因为 accountDAO 是一个动态代理,而您正在对其应用 Spring AOP 方面。它正在将方法调用转发给它的委托(它正在代理的原始对象)。

But when I explicitly print out getClass().getName() the results are different

System.out.println(accountDAO.getClass().getName());

And

System.out.println(this.getClass().getName());

Output-

com.luv2code.aopdemo.dao.AccountDAO$$EnhancerBySpringCGLIB$eb61b6

=======>>> Executing @Before Advice
com.luv2code.aopdemo.dao.AccountDAO

前者打印 CGLIB 代理的名称 class,后者打印目标 class 名称。

Also when I explicitly print hashCode() the results are different.

同样的原因:您正在打印代理与原始对象的哈希码。

Why are these differences there, I did not override any of these methods (At my end), does this has something related to AOP proxy?

嗯,在某种程度上你做到了。您应用了一个方面,导致代理创建。所以现在实际的 Spring bean 是一个代理,导致你上面描述的所有效果。从技术上讲,Spring 代理是一个 subclass(或接口实现,取决于您的设置以及您是否代理接口 ot class 类型)。代理保留对原始对象(其委托或目标对象)的引用,并使用附加功能对其进行装饰。这是一个众所周知的设计模式。 Spring 在整个框架中大量使用它。有关详细信息,请参阅

关于你的后续问题,根本原因和解释同上。一旦您了解 Spring AOP 使用动态代理并且相同的代理使用委托来实现 decorator pattern.

,这一切都非常简单和合乎逻辑。