Spring aop 破坏了原始代码?启用方面时,自动装配 bean 的字段变为空
Spring aop breaks original code? The field of the autowired bean becomes null when the aspect is enabled
启用方面后,BeanB
中的@Autowired bean成为代理,name
字段为空。为什么?如果我希望原代码能正常工作,我应该怎么做?
代码如下:
public class BeanA
{
@Value("jami")
//public String name;
String name; //package visiblity
}
public class BeanB
{
@Autowired
private BeanA beanA;
public void noLongerWorks()
{
System.out.println(beanA.name);
}
}
public class Main
{
public static void main(String[] args)
{
String[] configs = {"applicationContext.xml", "applicationContext-aop.xml"};//prints null
// String[] configs = {"applicationContext.xml"};//prints jami
ApplicationContext ctx = new ClassPathXmlApplicationContext(configs);
BeanB beanB = ctx.getBean(BeanB.class);
beanB.noLongerWorks();
}
}
------------ applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<bean class="aop.pack1.BeanA" />
<bean class="aop.pack1.BeanB" />
</beans>
------ applicationContext-aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy />
<bean class="aop.pack1.TestAspect" />
</beans>
@Aspect
public class TestAspect
{
@Pointcut("target(aop.pack1.BeanA)")
public void pointcut() {}
@Before("pointcut()")
public void advice()
{
System.err.println("___________advice__________");
}
}
编辑:
我想出了一个可能的解决方案。但是好像不是很干净。有什么优雅的方法吗?不更改现有代码?
我找到的解决方案:
is to make all the fields in BeanA private, and only access them via getter setters.
This approach, however, requires a lot of modification of the original code (e.g. the BeanA class).
你已经解决了这个问题,但是,我想分享这个 article 我看到它列出了 Spring AOP
可以做什么和不能做什么。
你的情况
Since it uses proxy-based AOP, only method-level advising is supported; it does not support field-level interception So join-points can be at method level not at field level in a class.
Only methods with public visibility will be advised: Methods with private, protected, or default visibility will not be advised.
只是一个建议,我认为创建具有 private or protected
可见性的字段并提供适当的 getter 和 setter 来访问它们也是一个很好的 OOP 实践。
这些 SO Q/A 可能有用
spring singleton bean fields are not populated
启用方面后,BeanB
中的@Autowired bean成为代理,name
字段为空。为什么?如果我希望原代码能正常工作,我应该怎么做?
代码如下:
public class BeanA
{
@Value("jami")
//public String name;
String name; //package visiblity
}
public class BeanB
{
@Autowired
private BeanA beanA;
public void noLongerWorks()
{
System.out.println(beanA.name);
}
}
public class Main
{
public static void main(String[] args)
{
String[] configs = {"applicationContext.xml", "applicationContext-aop.xml"};//prints null
// String[] configs = {"applicationContext.xml"};//prints jami
ApplicationContext ctx = new ClassPathXmlApplicationContext(configs);
BeanB beanB = ctx.getBean(BeanB.class);
beanB.noLongerWorks();
}
}
------------ applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<bean class="aop.pack1.BeanA" />
<bean class="aop.pack1.BeanB" />
</beans>
------ applicationContext-aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy />
<bean class="aop.pack1.TestAspect" />
</beans>
@Aspect
public class TestAspect
{
@Pointcut("target(aop.pack1.BeanA)")
public void pointcut() {}
@Before("pointcut()")
public void advice()
{
System.err.println("___________advice__________");
}
}
编辑: 我想出了一个可能的解决方案。但是好像不是很干净。有什么优雅的方法吗?不更改现有代码? 我找到的解决方案:
is to make all the fields in BeanA private, and only access them via getter setters.
This approach, however, requires a lot of modification of the original code (e.g. the BeanA class).
你已经解决了这个问题,但是,我想分享这个 article 我看到它列出了 Spring AOP
可以做什么和不能做什么。
你的情况
Since it uses proxy-based AOP, only method-level advising is supported; it does not support field-level interception So join-points can be at method level not at field level in a class.
Only methods with public visibility will be advised: Methods with private, protected, or default visibility will not be advised.
只是一个建议,我认为创建具有 private or protected
可见性的字段并提供适当的 getter 和 setter 来访问它们也是一个很好的 OOP 实践。
这些 SO Q/A 可能有用
spring singleton bean fields are not populated