请解释一下,为什么代理上的自我调用是在目标上执行的,而不是在代理上执行的?如果那是故意的,那为什么?如果代理是通过子类创建的,那么可以在每次方法调用之前执行一些代码,甚至在自我调用时也是如此。我试过了,我有自我调用的代理
public class DummyPrinter {
public void print1() {
System.out.println("print1");
}
public void print2() {
System.out.println("print2");
}
public void printBoth() {
print1();
print2();
}
}
public class PrinterProxy extends DummyPrinter {
@Override
public void print1() {
System.out.println("Before print1");
super.print1();
}
@Override
public void print2() {
System.out.println("Before print2");
super.print2();
}
@Override
public void printBoth() {
System.out.println("Before print both");
super.printBoth();
}
}
public class Main {
public static void main(String[] args) {
DummyPrinter p = new PrinterProxy();
p.printBoth();
}
}
Before print both
Before print1
print1
Before print2
print2
在这里,每个方法都在代理上调用。为什么在文档中提到在自我调用的情况下应该使用AspectJ?
请阅读Spring手册中的这一章,到时你就明白了。甚至在那里使用了术语“自我调用”。如果你仍然不明白,请随时提出后续问题,只要他们是在上下文中。
更新:好的,现在,在我们确定你真的读了那一章,在重新阅读你的问题和分析你的代码之后,我发现这个问题实际上是相当深刻的(我甚至反对它),值得更详细地回答。
您的误解是动态代理是如何工作的,因为它们不像示例代码中那样工作。让我将对象ID(哈希代码)添加到日志输出中,以便对您自己的代码进行说明:
package de.scrum_master.app;
public class DummyPrinter {
public void print1() {
System.out.println(this + " print1");
}
public void print2() {
System.out.println(this + " print2");
}
public void printBoth() {
print1();
print2();
}
}
package de.scrum_master.app;
public class PseudoPrinterProxy extends DummyPrinter {
@Override
public void print1() {
System.out.println(this + " Before print1");
super.print1();
}
@Override
public void print2() {
System.out.println(this + " Before print2");
super.print2();
}
@Override
public void printBoth() {
System.out.println(this + " Before print both");
super.printBoth();
}
public static void main(String[] args) {
new PseudoPrinterProxy().printBoth();
}
}
de.scrum_master.app.PseudoPrinterProxy@59f95c5d Before print both
de.scrum_master.app.PseudoPrinterProxy@59f95c5d Before print1
de.scrum_master.app.PseudoPrinterProxy@59f95c5d print1
de.scrum_master.app.PseudoPrinterProxy@59f95c5d Before print2
de.scrum_master.app.PseudoPrinterProxy@59f95c5d print2
看见没?总是有相同的对象ID,这一点也不奇怪。由于多态性,您的“代理”(它不是真正的代理,而是静态编译的子类)的自调用可以工作。这由Java编译器负责。
现在请记住我们这里讨论的是动态代理,即运行时创建的子类和对象:
package de.scrum_master.app;
public class DelegatingPrinterProxy extends DummyPrinter {
DummyPrinter delegate;
public DelegatingPrinterProxy(DummyPrinter delegate) {
this.delegate = delegate;
}
@Override
public void print1() {
System.out.println(this + " Before print1");
delegate.print1();
}
@Override
public void print2() {
System.out.println(this + " Before print2");
delegate.print2();
}
@Override
public void printBoth() {
System.out.println(this + " Before print both");
delegate.printBoth();
}
public static void main(String[] args) {
new DelegatingPrinterProxy(new DummyPrinter()).printBoth();
}
}
de.scrum_master.app.DelegatingPrinterProxy@59f95c5d Before print both
de.scrum_master.app.DummyPrinter@5c8da962 print1
de.scrum_master.app.DummyPrinter@5c8da962 print2
这就是您在使用动态代理的Spring AOP或Spring的其他部分,甚至使用JDK或CGLIB代理的非Spring应用程序中看到的行为。
这是一个特点还是一个局限?作为一个AspectJ(不是Spring AOP)用户,我认为这是一个限制。也许其他人会认为这是一个特性,因为根据Spring中实现代理的方式,原则上您可以在运行时动态注册方面建议或拦截器,即每个原始对象(委托)都有一个代理,但对于每个代理,在调用委托的原始方法之前和/或之后都有一个动态的拦截器列表。在非常动态的环境中,这可能是一件好事。我不知道你要多久用一次。但是在AspectJ中,您还有if()
切入点指示符,您可以在运行时使用它来确定是否应用某些建议(拦截器的AOP语言)。
我找不到任何原因来解释为什么每个自动连接的bean都不是通过代理自动连接的。我知道,因为事务注释不起作用,我在eclipse中调试时检查了自动连线组件。当然,每个组件都实现了一些接口,我使用了与接口相关的注释。我只有一种aop配置: 我将JPA与hibernate、spring mvc、spring webflow、spring security和spring数据一起使用。扩展组织的接口。spri
当我编写一些spring代码时,我使用了带有class和annotation-config的Spring4。我已经声明一个bean将接口实现为组件。我正在尝试制作另一个bean来依赖于它的接口时间。但它不起作用,因为spring抛出一个错误,在该名称中找不到bean。我想这可能是因为只靠和实体类的自动电线工作,但我不知道为什么它会这样设置?有人能解释为什么依赖注释不允许类型自动连接到接口吗? 简单
我正在使用forEach循环一个nodeList。我的代码如下 此代码引发错误为 未捕获的TypeError:Array.Foreach不是函数 然而,一些较旧的浏览器还没有实现nodelist.foreach()和array.from()。但是这些限制可以通过使用array.prototype.foreach()来规避(本文档中有更多内容)。 参考:MDN
问题内容: 我有一个expressjs应用程序,在特定的路由上,我调用了一个函数,该函数通过使用数据库文档作为参数来响应数据库中的用户。我使用基于promise的库,并且想在将数据库文档放入响应中的回调内联。但是当我这样做时程序会失败。有人可以解释为什么吗?我还想知道为什么内联调用才能真正起作用。两种方法和之间有一些根本区别吗? 这是一个有效和无效的示例。假定返回用户文档的承诺。 问题答案: 像这
为什么JSF2/Facelet的ui:repeat不接受java。util。迭代器的值?可以在迭代器后面隐藏如此多的实现和内存节约,因为长度不需要知道,所以拥有它是非常有用的。但是相反,我需要将迭代器转换为列表,并抛弃所有优点,以便ui:repeat。 可能有阶段、时间或可序列化的原因,但我对可用文档的浏览并没有给出这些原因。我们还没有使这一不可能成为可能的科学吗?
我有一个接口,有两个实现。使用哪个实现取决于环境(生产、开发、测试……)。因此,我使用Spring配置文件。我正在使用一个配置文件来实例化正确的实现。 当Spring容器启动时(使用特定的概要文件),正确的bean就会被带入类中,所有的工作都很好。 我还有一个测试类,我想在其中autowire这个bean。我正在使用@mock进行自动化。在测试类中,配置文件被设置为“test-unit”。因此,我