如何将对象作为参数传递给弹簧方面



假设我需要用@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方法中,此处将不允许使用。在这种情况下,有什么弹簧特性可以用来解耦IPhoneMusicAspect吗?

!注:感谢@kriegaex的校对

这是一个初步答案,因为内容不适合作为注释

当我看到你更新的问题中的代码时,有些事情让我觉得很奇怪:

  • 我想知道为什么每个人都如此渴望总是将方面与注释结合使用。为什么不使用直接针对感兴趣的包、类或方法的切入点呢?所有这些注释污染是可怕的,如果不是绝对必要的话。理想情况下,应用程序代码应该完全不知道方面的存在
  • 您使用@annotation切入点指示符不正确。应该是@annotation(MusicAround)而不是@annotation(@MusicAround)。但是,只有当注释恰好与方面位于完全相同的包中时,这才有效,否则您需要@annotation(fully.qualified.package.name.MusicAround)
  • 您使用了一个MusicAspect,但随后声明了一个MinstrelAroundAdvicebean。这似乎不匹配。另外,一个方面就是一个方面,它里面实际做事情的方法就是建议。因此,一个方面的类名*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中注册IPhonebean。其余部分保持不变。

@Configuration
@EnableAspectJAutoProxy
public class ApplicationConfig {
// ... other beans omitted
@Bean 
public IPhone iphone() {
return new IPhone();
}
}

代码通过了我笔记本电脑的单元测试。

相关内容

  • 没有找到相关文章

最新更新