假设我需要用@MusicAround
建议来增强shower()
方法,以便在执行shower()
方法之前和之后给我一些音乐。
public class Me {
@MusicAround
public void shower() {
// shower code omitted
}
}
首先,我创建了新的注释@MusicAround
。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MusicAround {
然后将其与方面MusicAspect
绑定。
@Aspect
public class MusicAspect {
@Around("@annotation(MusicAround)")
public Object musicAround(ProceedingJoinPoint joinPoint) throws Throwable {
IPhone iphone = new IPhone();
Iphone.music();
joinPoint.proceed();
iphone.music();
}
}
将MusicAspect
配置为Bean
。@EnableAspectJAutoProxy
注释让spring为我封装方面代理。
@Configuration
@EnableAspectJAutoProxy
public class ApplicationConfig {
// ... other beans omitted
@Bean
public MusicAspect musicAspect() {
return new MusicAspect();
}
}
在main方法中,从上下文中获取Me
实例,并执行shower()
方法。
public static void main(String[] args) {
try {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
Me me = context.getBean(Me.class);
me.shower();
context.close();
} catch (ApplicationContextException ace) {
// handle exception
}
}
现在我可以在淋浴时欣赏音乐了。
<hey jude>
I'm showering
<don't be so serious>
问题是以这种方式MusicAspect
类与IPhone
类耦合。我想通过注入IPhone
对象作为参数来解耦它们,如下所示,
@Aspect
public class MusicAspect {
@Around("@annotation(MusicAround)")
public Object musicAround(ProceedingJoinPoint joinPoint, IPhone iphone) throws Throwable {
iphone.music();
joinPoint.proceed();
iphone.music();
}
}
当然,第二个参数";iphone";在CCD_ 14方法中,此处将不允许使用。在这种情况下,有什么弹簧特性可以用来解耦IPhone
和MusicAspect
吗?
!注:感谢@kriegaex的校对
这是一个初步答案,因为内容不适合作为注释
当我看到你更新的问题中的代码时,有些事情让我觉得很奇怪:
- 我想知道为什么每个人都如此渴望总是将方面与注释结合使用。为什么不使用直接针对感兴趣的包、类或方法的切入点呢?所有这些注释污染是可怕的,如果不是绝对必要的话。理想情况下,应用程序代码应该完全不知道方面的存在
- 您使用
@annotation
切入点指示符不正确。应该是@annotation(MusicAround)
而不是@annotation(@MusicAround)
。但是,只有当注释恰好与方面位于完全相同的包中时,这才有效,否则您需要@annotation(fully.qualified.package.name.MusicAround)
- 您使用了一个
MusicAspect
,但随后声明了一个MinstrelAroundAdvice
bean。这似乎不匹配。另外,一个方面就是一个方面,它里面实际做事情的方法就是建议。因此,一个方面的类名*Advice
是完全错误的。最好使用*Aspect
或其他适当描述方面功能的内容。在这种情况下,MusicAspect
对我来说似乎很好
现在关于你的实际问题,我仍然不清楚。它是关于如何将另一个bean注入(自动连接(到方面实例中吗?
当然我不被允许这么做。
为什么"当然"?什么是不允许的?你是怎么注意到的?有什么不起作用吗?你收到错误信息了吗?堆栈跟踪?请解释清楚你尝试了什么,预期的结果是什么,以及发生了什么。让你的问题重现。不幸的是,您的代码片段无法做到这一点。想象一下,在你没有看到完整的代码,也没有理解问题所需的其他上下文信息的情况下,其他人会问你同样的问题。你能回答吗?如果你的助手不理解这个问题,他们如何回答你的问题?建议您了解什么是MCVE。
在@k-wasilewski和@creegaex的帮助下解决的问题。谢谢兄弟。
答案是@Autowired
注释。
将IPhone
定义为MusicAspect
类的一个字段。添加@Autowired
标记,它告诉spring上下文为我们初始化IPhone
实例
@Aspect
public class MusicAspect {
@Autowired
private IPhone iphone;
@Around("@annotation(MusicAround)")
public Object musicAround(ProceedingJoinPoint joinPoint) throws Throwable {
Iphone.music();
joinPoint.proceed();
iphone.music();
}
}
不要忘记在ApplicationConfig
中注册IPhone
bean。其余部分保持不变。
@Configuration
@EnableAspectJAutoProxy
public class ApplicationConfig {
// ... other beans omitted
@Bean
public IPhone iphone() {
return new IPhone();
}
}
代码通过了我笔记本电脑的单元测试。