복붙노트

[SPRING] 객체 자체에서 AOP 프록시 가져 오기

SPRING

객체 자체에서 AOP 프록시 가져 오기

Spring에서 주어진 객체의 프록시를 가져올 수 있습니까? 하위 클래스의 함수를 호출해야합니다. 그러나 분명히 직접 전화를 걸 때 그 측면은 적용되지 않습니다. 다음은 그 예입니다.

public class Parent {

    public doSomething() {
        Parent proxyOfMe = Spring.getProxyOfMe(this); // (please)
        Method method = this.class.getMethod("sayHello");
        method.invoke(proxyOfMe);
    }
}

public class Child extends Parent {

    @Secured("president")
    public void sayHello() {
        System.out.println("Hello Mr. President");
    }
}

나는 이것을 달성하는 방법을 발견했다. 그것은 작동하지만 매우 우아하지는 않습니다 :

public class Parent implements BeanNameAware {

    @Autowired private ApplicationContext applicationContext;
    private String beanName; // Getter

    public doSomething() {
        Parent proxyOfMe = applicationContext.getBean(beanName, Parent.class);
        Method method = this.class.getMethod("sayHello");
        method.invoke(proxyOfMe);
    }
}

해결법

  1. ==============================

    1.이 해킹은 매우 어색합니다. 코드를 리팩토링하거나 AspectJ 직조를 사용해보십시오. 당신은 경고를받을 수 있습니다, 여기 해결책입니다

    이 해킹은 매우 어색합니다. 코드를 리팩토링하거나 AspectJ 직조를 사용해보십시오. 당신은 경고를받을 수 있습니다, 여기 해결책입니다

    AopContext.currentProxy()
    

    JavaDoc. 나는 여기에 여기에 대해 블로깅했다.

  2. ==============================

    2.Tomasz가 제안한대로 AopContext.currentProxy ()가 작동합니다. 프록시 된 클래스 외부에서 작동하는 더 일반적인 솔루션은 객체를 org.springframework.aop.framework.Advised로 캐스팅하고 .getTargetSource (). getTarget ()을 얻는 것입니다.

    Tomasz가 제안한대로 AopContext.currentProxy ()가 작동합니다. 프록시 된 클래스 외부에서 작동하는 더 일반적인 솔루션은 객체를 org.springframework.aop.framework.Advised로 캐스팅하고 .getTargetSource (). getTarget ()을 얻는 것입니다.

    전자 (프록시 객체에서 실제 객체를 가져 오는 것)는 꼭 필요한 것은 아닙니다. 반면에 대상 프록시를 얻는 것은 일부 기능을 추가하기 위해 기존 bean을 검사하는 유틸리티 클래스에서 유용 할 수 있습니다.

  3. ==============================

    3.Bean 포스트 프로세서를 사용하여 대상 bean에서 프록시에 대한 참조를 설정할 수 있습니다. Spring의 특성을 빈에서 단일 클래스로 이동합니다.

    Bean 포스트 프로세서를 사용하여 대상 bean에서 프록시에 대한 참조를 설정할 수 있습니다. Spring의 특성을 빈에서 단일 클래스로 이동합니다.

    후 처리기

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    public class SelfReferencingBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof SelfReferencingBean) {
                ((SelfReferencingBean) bean).setProxy(bean);
            }
            return bean;
        }
    }
    

    문맥

    applicationContext.xml에 포스트 프로세서를 등록하십시오.

    <bean id="srbpp" class="SelfReferencingBeanPostProcessor"/>
    

    각 Bean은 자체 참조를 구현하여 사후 프로세서에 프록시에 대한 참조가 필요함을 알립니다.

    public interface SelfReferencingBean {
        void setProxy(Object proxy) ;
    }
    

    이제 프록시를 통해 자신을 호출해야하는 각 bean에서 setProxy를 구현하십시오.

    public class MyBean implements SelfReferencingBean {
        MyBean proxy;
    
        @Override
        public void setProxy(Object proxy) {
            this.proxy = (MyBean) proxy;
        }
    }
    

    메소드를 직접 호출 할 때 bean의 유형에 프록시를 전달하는 것을 신경 쓸 필요가 없다면이 마지막 비트의 코드를 bean 기본 클래스에 넣을 수 있습니다. Method.invoke를 거치므로 캐스트가 필요하지 않습니다.

    약간의 작업으로 나는 이것을 @Autowired라는 어노테이션 프로세서로 변환 할 수있을 것이라고 확신한다. 생각해 보니, @Autowired 자체를 사용하여 자체 참조를 추가하려고 시도했는지 기억하지 못합니다.

    public class MyBean implements SelfReferencingBean {
        @Autowired MyBean proxy;
    }
    
  4. from https://stackoverflow.com/questions/7482666/get-aop-proxy-from-the-object-itself by cc-by-sa and MIT license