2016-01-03 64 views
0

我对Spring很新,我想使用Spring AOP在POJO getter被调用时能够引发建议。Spring AOP - 设置关于POJO getter的建议 - 不建议

我创建了一个简单POJO

package com.atlas.datastore.datadomain; 

import org.springframework.data.mongodb.core.mapping.Document; 
import org.springframework.stereotype.Component; 

@Component 
public class Person 
{ 
    private String name; 

    public String getName() { 
     System.out.println(name); 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

我创建了名称吸气的看点:

package com.atlas.datastore.aspects; 

import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Before; 
import org.aspectj.lang.annotation.Pointcut; 
import org.springframework.stereotype.Component; 

@Component 
@Aspect 
public class personAspect { 
    @Pointcut("execution(* com.atlas.datastore.datadomain.Person.getName())") 
    private void getName() {} 

    @Before("getName()") 
    public void doBeforeTask(){ 
     System.out.println("My name is: "); 
    } 
} 

我创建了一个控制器(春季启动简单的应用程序)使用的getter:

package com.example.Controller; 

import com.atlas.datastore.datadomain.*; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.*; 

@RestController 
@RequestMapping("/person") 
public class PersonController { 

    @Autowired 
    private Person person; 

    @RequestMapping(value = "/{personId}", method = RequestMethod.GET) 
    @ResponseBody() 
    public Person personAction(@PathVariable String personId) { 

     person.setName("John"); 

     person.getName(); 

     return person; 
    } 
} 

当我运行应用程序时,一切正常,我可以看到意见正在被解雇。

我现在的问题是我不想auto-wire Person对象。当我创建一个人与一个默认的构造函数(使用new关键字),我看到advice没有被解雇:

package com.example.Controller; 

import com.atlas.datastore.datadomain.*; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.*; 

@RestController 
@RequestMapping("/person") 
public class PersonController { 

    @RequestMapping(value = "/{personId}", method = RequestMethod.GET) 
    @ResponseBody() 
    public Person personAction(@PathVariable String personId) { 

     Person person = new Person(); 

     person.setName("John"); 

     person.getName(); 

     return person; 
    } 
} 

在我的配置我使用下面的注释:

@EnableAspectJAutoProxy(proxyTargetClass = true) 

我可以在日志中看到以下的输出:

18:12:40.152 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person' 
18:12:40.152 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'person' 
18:12:40.152 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'person' to allow for resolving potential circular references 
18:12:40.153 [main] DEBUG o.s.a.a.a.AnnotationAwareAspectJAutoProxyCreator - Creating implicit proxy for bean 'person' with 0 common interceptors and 2 specific interceptors 
18:12:40.153 [main] DEBUG o.s.aop.framework.CglibAopProxy - Creating CGLIB proxy: target source is SingletonTargetSource for target object [[email protected]] 
18:12:40.154 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'person' 

我会感激你的帮助

回答

1

使用new运算符直接创建一个像Person person = new Person()这样的实例绕过了Spring,所以Spring没有机会在此对象中注入依赖关系或代理此对象。

为了让春天注入的依赖或者用于new运营商使用,我们需要注释的Person对象@Configurable以上场景代理,配置AnnotationBeanConfigurerAspect,使用Spring LoadTimeWeaving并运行-javaagent .....

您可以找到应用程序此示例的使用情况在https://dzone.com/articles/domain-object-dependency-injection-with-spring

+0

感谢您为此Madhusudana!我还发现了这样的评论:“有些事情你不能轻易或高效地用Spring AOP来完成,比如在http://docs.spring.io/spring/中提供非常细粒度的对象(比如域对象) docs/current/spring-framework-reference/html/aop.html#aop-introduction-spring-defn。从解决方案,我觉得我在这里走错了路。 – user3811709

+0

@ user3811709我不会说这是一种错误的做法,它取决于用例。如果你觉得使用上面的@ Configurable/AspectJ路由对于你的用例来说太重/太重了,我看到的一个选择是将Person类配置为原型bean,并从适当的getBean()方法中获取Person对象在您的控制器中实现Spring ApplicationContext实现。通过这种方式,Spring将在返回它之前获得AOP代理Person对象的机会。 –

+0

是的,我试图让这个工作一段时间。我无法将所需的javaagent参数添加到我的JVM - 我无法找到有效的javagent。当我自动装配人员作为依赖时,我能够得到这个工作,但这对我来说不是一个好的解决方案。 Person对象将被用作Data Domain对象(实体)以及Spring Data设置 - 我可以从我的存储库中获取一个列表,我无法控制它们实例化的方式。再次感谢您的跟进! – user3811709

0

,而不是添加到@Pointcut域对象的: com.atlas.datastore.datadomain.Person.getName()

考虑创建一个服务,而不是它接受一个Person对象作为参数。将@Pointcut添加到服务方法。 将服务注入到您的Web控制器中,然后调用通过“新”Person的服务。

+0

谢谢!对我来说这绝对是一个更简单的解决方案..我仍然希望能够以更透明的方式利用这些方法为我的客户端(应用程序开发人员使用数据层) – user3811709