복붙노트

[SPRING] 인터페이스 나 TARGET_CLASS : 나는 프록시 모드를 선택해야합니까?

SPRING

인터페이스 나 TARGET_CLASS : 나는 프록시 모드를 선택해야합니까?

내 객체를 저장할 수있는 방법을 찾고 있어요 그리고 가장 좋은 방법은 프록시를 사용하는 것 같다. 내가 사용해야 하나의 인터넷, 2 주석을 발견 :

@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)

또는

@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )

또한, 프록시 @Component를 사용하는 것보다 사용하는 가장 좋은 방법이라는 것이 사실이다 @Scope ( "세션") 또는 사용 @SessionAttributes?

해결법

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

    1.당신은 그 주석의 각 자신을 위해 선택하는 무엇을 이해해야합니다. 여기에, Javadoc을 참조하십시오. 더 자세한 설명을 계속합니다.

    당신은 그 주석의 각 자신을 위해 선택하는 무엇을 이해해야합니다. 여기에, Javadoc을 참조하십시오. 더 자세한 설명을 계속합니다.

    첫번째

    @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
    

    생성

    즉, 프록시는 대상 객체의 클래스가 구현하는 인터페이스의 하위 유형 수 있지만 대상 객체 클래스 자체의 서브 클래스되지 않습니다.

    기본적으로 Spring은 다음을 수행합니다

    public class Example {
        public static void main(String[] args) throws Exception {
            Foo target = new Foo();
            InvocationHandler proxyHandler = ... // some proxy specific logic, likely referencing the `target`
    
            // works fine
            Printable proxy = (Printable) Proxy.newProxyInstance(Example.class.getClassLoader(),
                    target.getClass().getInterfaces(), proxyHandler);
    
            // not possible, ClassCastException
            Foo foo = (Foo) proxy; 
        }
    
        public static class Foo implements Printable {
            @Override
            public void print() {
            }
        }
    
        public interface Printable {
            void print();
        }
    }
    

    프록시는 유형 푸의되지 않습니다 반환하고 따라서 해당 유형의 목표에 주입 할 수 없다. 예를 들어, 봄 같은 필드에 주입 할 수 없게됩니다

    @Autowired
    private Foo foo;
    

    그러나 성공적으로 같은 필드에 프록시를 주입합니다

    @Autowired
    private Printable printable;
    

    프록시에 대한 모든 호출은 (일반적으로 대상 객체에 다음 대표를 일부 사용 사례 특정 논리를 수행)에의 InvocationHandler에 의해 처리됩니다.

    두 번째 주석

    @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )
    

    생성

    인터페이스 또한, CGLIB 봄으로 그 클래스 대상의 클래스의 서브 클래스입니다 프록시를 만들 수있을 것입니다. 본질적으로, 그것은 다음과 같은 작업을 수행

    Foo target = new Foo();
    net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer();
    enhancer.setInterfaces(target.getClass().getInterfaces());
    enhancer.setSuperclass(target.getClass());
    net.sf.cglib.proxy.MethodInterceptor interceptor = ... // some proxy specific logic, likely referencing the `target`
    enhancer.setCallback(interceptor);
    
    // works fine
    Foo proxy = (Foo) enhancer.create();
    

    CGLIB는 푸의 서브 클래스 (푸의 생성자를 호출)를 인스턴스화하는 새로운 클래스를 생성합니다. 프록시에 대한 모든 호출은 (일반적으로 몇 가지 사용 사례를 다음 특정 논리와 대상 객체에 위임을 수행) 제공된 콜백에 의해 차단됩니다.

    프록시 클래스 푸 연장 이후 마찬가지로 스프링 필드에 프록시를 삽입 (또는 생성자 / 메소드 파라미터)

    @Autowired
    private Foo injectMe;
    

    이 모든 것은 당신이 인터페이스에 프로그래밍하는 경우, 다음 ScopedProxyMode.INTERFACES이 충분하다 말할 수 있습니다. 당신이하지 않은 경우, 다음 ScopedProxyMode.TARGET_CLASS를 사용합니다.

    @SessionAttributes를 사용에 관해서는, 세션 범위 콩의 대안이 아니다. 세션 속성은 콩 아닌, 단지가 개체입니다. 그들은 전체 라이프 사이클, 사출 기능, bean가있을 수 있습니다 프록시 동작을 소유하지 않습니다.

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

    2.당신이 세션에서 원두를 저장하려면, 그렇지 않으면 @SessionAttributes를 사용 @Scope을 사용합니다. TARGET_CLASS를 사용하지 않을 경우 클래스가 어떤 인터페이스를 구현하는 경우, @Scope을 사용하는 경우 다음, 인터페이스 프록시 모드를 사용합니다.

    당신이 세션에서 원두를 저장하려면, 그렇지 않으면 @SessionAttributes를 사용 @Scope을 사용합니다. TARGET_CLASS를 사용하지 않을 경우 클래스가 어떤 인터페이스를 구현하는 경우, @Scope을 사용하는 경우 다음, 인터페이스 프록시 모드를 사용합니다.

    일반적으로 서비스는 JDK 프록시 (INTERFACES 모드)의 사용을 허용하는 인터페이스를 구현합니다. 그없는 경우에 해당하지만 다음 CGLIB 프록시를 생성 TARGET_CLASS를 사용합니다.

    콩이 인터페이스를 구현하고 있지 않는 경우 인터페이스 사용은 최후의 수단으로 가능하고 TARGET 경우에 사용한다.

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

    3.위의 댓글에서 제공하는 블로그 게시물을 통해가는 동안, 나는 인터페이스 기반의 프록시의 단점을 알리는 메모를 발견했다.

    위의 댓글에서 제공하는 블로그 게시물을 통해가는 동안, 나는 인터페이스 기반의 프록시의 단점을 알리는 메모를 발견했다.

    이후에, 사용자 플레밍 Jønsson이 게시 :

  4. from https://stackoverflow.com/questions/21759684/interfaces-or-target-class-which-proxymode-should-i-choose by cc-by-sa and MIT license