복붙노트

[SPRING] 어떤 범위 프록시 봄에?

SPRING

어떤 범위 프록시 봄에?

우리가 알다시피 봄 (examle에 대한 @Scheduled @Transactional) 몇 가지 기능을 추가하는 프록시를 사용합니다. (클래스가 비어 있지 않은 인터페이스를 구현해야합니다) JDK 동적 프록시를 사용하거나 CGLIB 코드 생성기를 사용하여 자식 클래스를 생성 -이 옵션이 있습니다. 나는 항상 프록시 모드가 나를 JDK 동적 프록시와 CGLIB 사이에서 선택할 수 있습니다 생각했다.

하지만 내 가정이 잘못 보여줍니다 예제를 만들 수 있었다 :

하나씩 일어나는 것:

@Service
public class MyBeanA {
    @Autowired
    private MyBeanB myBeanB;

    public void foo() {
        System.out.println(myBeanB.getCounter());
    }

    public MyBeanB getMyBeanB() {
        return myBeanB;
    }
}

원형:

@Service
@Scope(value = "prototype")
public class MyBeanB {
    private static final AtomicLong COUNTER = new AtomicLong(0);

    private Long index;

    public MyBeanB() {
        index = COUNTER.getAndIncrement();
        System.out.println("constructor invocation:" + index);
    }

    @Transactional // just to force spring create proxy
    public long getCounter() {
        return index;
    }
}

본관:

MyBeanA beanA = context.getBean(MyBeanA.class);
beanA.foo();
beanA.foo();
MyBeanB myBeanB = beanA.getMyBeanB();
System.out.println("counter: " + myBeanB.getCounter() + ", class=" + myBeanB.getClass());

산출:

constructor invocation:0
0
0
counter: 0, class=class test.pack.MyBeanB$$EnhancerBySpringCGLIB$$2f3d648e

여기에서 우리는 두 가지를 볼 수 있습니다

1 - MyBeanB 한 번만 인스턴스화 2 - CGLIB 사용 MyBeanB의 봄 @Transactional 기능을 추가하려면

나에게 올바른 MyBeanB 정의를 보자 :

Service
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyBeanB {

이 경우에 출력은 :

constructor invocation:0
0
constructor invocation:1
1
constructor invocation:2
counter: 2, class=class test.pack.MyBeanB$$EnhancerBySpringCGLIB$$b06d71f2

여기에서 우리는 두 가지를 볼 수 있습니다

1 - MyBeanB 3 번 인스턴스화 2 - CGLIB 사용 MyBeanB의 봄 @Transactional 기능을 추가하려면

당신은 무슨 일이 일어나고 있는지 설명 할 수 있을까요? 어떻게 프록시 모드는 정말 작동?

나는 문서를 읽었습니다 :

/**
 * Specifies whether a component should be configured as a scoped proxy
 * and if so, whether the proxy should be interface-based or subclass-based.
 * <p>Defaults to {@link ScopedProxyMode#DEFAULT}, which typically indicates
 * that no scoped proxy should be created unless a different default
 * has been configured at the component-scan instruction level.
 * <p>Analogous to {@code <aop:scoped-proxy/>} support in Spring XML.
 * @see ScopedProxyMode
 */

그러나 그것은 나를 위해 분명하지 않다

또한 나는 또 하나의 사건을 조사 :

나는 MyBeanB에서 인터페이스를 exctracted :

public interface MyBeanBInterface {
    long getCounter();
}



@Service
public class MyBeanA {
    @Autowired
    private MyBeanBInterface myBeanB;


@Service
@Scope(value = "prototype", proxyMode = ScopedProxyMode.INTERFACES)
public class MyBeanB implements MyBeanBInterface {

이 경우에 출력은 :

constructor invocation:0
0
constructor invocation:1
1
constructor invocation:2
counter: 2, class=class com.sun.proxy.$Proxy92

여기에서 우리는 두 가지를 볼 수 있습니다

1 - MyBeanB 3 번 인스턴스화 2 - MyBeanB의 봄 @Transactional 기능을 추가하려면 JDK 동적 프록시를 사용

해결법

    from https://stackoverflow.com/questions/58170627/what-a-scoped-proxy-is-in-spring by cc-by-sa and MIT license