Spring aop打破原始代码?启用方面时,自动装配的bean的字段将变为null

时间:2018-01-04 04:12:57

标签: java spring aop

启用方面后,foo = "ALL CAPS" bar = foo.lower bar >>> <built-in method lower of str object at 0x1038e1570> bar() >>> 'all caps' 中的@Autowired bean成为代理,BeanB字段为空。为什么?如果我希望原始代码正常工作,我该怎么办?

以下是代码:

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);
    }
}

---------- applicationContext.xml

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-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: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>
<?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__________");
    }
}

1 个答案:

答案 0 :(得分:1)

您已经找到了问题但是,我想分享这个article我遇到了Spring AOP可以做什么和不能做什么。

在你的情况下

  
      
  1. 由于它使用基于代理的AOP,因此仅支持方法级建议;它不支持字段级拦截所以连接点可以在方法级别而不是在类中的字段级别。

  2.   
  3. 仅建议具有公众可见度的方法:不建议具有私有,受保护或默认可见性的方法。

  4.   

只是一个推荐,我认为创建具有private or protected可见性的字段并提供适当的getter和setter来访问它们也是一个很好的OOP实践。

这些SO Q / A可能有用

Spring AOP - get old field value before calling the setter

spring singleton bean fields are not populated

Spring AOP CGLIB proxy's field is null