java - SpringAOP 介绍与 AspectJ 使用 Annotations
问题描述
我正在学习介绍(在 AspectJ 中称为类型间声明)。我从使用 xml的 AspectJ 的 SpringAOP 介绍中得到了一个示例。我正在尝试使用 annotations 复制相同的内容,但我不知道如何继续。我在互联网上做了很多研究,但找不到任何样本。你能帮我解决这个问题吗?
性能测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ConcertConfig.class)
public class PerformanceTest {
@Autowired
public Audience audience;
@Autowired
public Performance liveOpera;
@Autowired
public EncoreableIntroducer encoreable;
@Test
public void testPerformance(){
liveOpera.perform();
}
}
LiveOpera.class
public class LiveOpera implements Performance{
@Override
public void perform() {
System.out.println("Live Opera Performance Started");
}}
Encoreable.interface
public interface Encoreable {
public void performEncore();
}
DefaultEncoreable.class
public class DefaultEncoreable implements Encoreable {
@Override
public void performEncore() {
System.out.println("WoW!! What an encore performance!!");
}
}
ConcertConfig.class
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConcertConfig {
@Bean
public Audience audience(){
return new Audience();
}
@Bean
public LiveOpera opera(){
return new LiveOpera();
}
@Bean
public EncoreableIntroducer encoreable(){
return new EncoreableIntroducer();
}
}
性能接口
public interface Performance {
public void perform();
}
EncoreableIntroducer.class
@Aspect
public class EncoreableIntroducer {
@DeclareParents(value="com.example.introduction.Performance+",
defaultImpl=DefaultEncoreable.class)
public static Encoreable encoreable;
}
观众类
@Aspect
public class Audience {
@Pointcut("execution(** com.example.introduction.Performance.perform(..))")
public void performance() {
}
public void silenceMobilePhones() {
System.out.println("Silencing Mobile Phones");
}
public void takeSeats() {
System.out.println("Taking seats");
}
public void applause() {
System.out.println("CLAP CLAP CLAP!!");
}
public void demandRefund() {
System.out.println("Need a Refund!!");
}
@Around("performance()")
public void wrapPerformance(ProceedingJoinPoint jp) {
try {
silenceMobilePhones();
takeSeats();
jp.proceed();
applause();
} catch (Throwable e) {
System.out.println(e);
e.printStackTrace();
demandRefund();
}
}
}
输出:在 PerformanceTest.class 中执行 @Test 方法时
Silencing Mobile Phones
Taking seats
Live Opera Performance Started
CLAP CLAP CLAP!!
请告诉我,如何使用 AspectJ-Introductions 使用 EncoreableIntroducer.class 中的方面,以便可以使用 DefaultEncoreable.class 中的 perform() 方法?
在使用 AspectJ Introductions 时期望如下输出:
Silencing Mobile Phones
Taking seats
WoW!! What an encore performance!!
Live Opera Performance Started
CLAP CLAP CLAP!!
解决方案
您在这里遇到了几个问题:
- 您正在使用实现相同方法的两个接口(
Performance
vs. )。Encoreable
为什么? - 您正在尝试引入
LiveOpera
它已经拥有的方法,即void perform()
. 可能您的意图是覆盖原来的。这在 Spring AOP 和 AspectJ 中都不起作用。您只能引入目标类中尚不存在的方法。 - 您正试图在另一个方面 B 中拦截方面 A 引入的方法。据我所知,这只适用于 AspectJ,而不适用于 Spring AOP。我不是 Spring 用户,但很快尝试了一下,但它不起作用。在 AspectJ 中复制您的情况时,它起作用了。所以你可以做的是在你的 Spring 应用程序中通过 LTW 激活 AspectJ并修改你的代码以使其工作,避免我描述的前两个问题。
更新并回答评论中提出的问题:
首先,我摆脱@Bean
了配置类中的手动方法,因为无论如何您都启用了组件扫描。相反,我只是在类和两个方面添加了@Component
注释。LiveOpera
你的方法也有效,但我更喜欢这个:
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConcertConfig {}
看起来更干净,不是吗?只是不要忘记@Component
它们所属的注释。
现在,真正的解决方案。在这方面,将您的建议更改为:
@Around("performance() && this(encoreable)")
public void wrapPerformance(ProceedingJoinPoint jp, Encoreable encoreable) {
try {
silenceMobilePhones();
takeSeats();
encoreable.performEncore();
jp.proceed();
applause();
} catch (Throwable e) {
System.out.println(e);
e.printStackTrace();
demandRefund();
}
}
推荐阅读
- regex - 如何使用空手道中的包含将字符串列表与子字符串匹配
- azure - 如何在 Azure 门户中的两个现有 VM 之间创建网络连接
- angular - ESLint:无法启动语言服务进程/HLS .ts 扩展存在问题
- c# - 将数据从datagridview保存到excel文件
- graph - 删除图表视图中没有数据的区间
- angular - 当使用primeng选择子节点时,我必须将连字符放在父节点上
- python - 当我在邮递员中将其传递给删除方法时,我得到 dict 对象没有更低的属性
- csv - 如何获取csv文件中的总行数
- shopify - 如何在 Shopify 中有效地检索产品所属的所有集合的列表?
- php - 重启apache服务器后,php脚本不再工作