[F-Lab 챌린지 37일차 TIL]

성수데브리·2023년 8월 3일
0

f-lab_java

목록 보기
29/73

프로젝트

객체 생성 방법

static factory method

장점

  • 명시적인 네이밍이 가능하다.
  • 객체 캐싱
    /**
         * Cache to support the object identity semantics of autoboxing for values between
         * -128 and 127 (inclusive) as required by JLS.
         *
         * The cache is initialized on first usage.  The size of the cache
         * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
         * During VM initialization, java.lang.Integer.IntegerCache.high property
         * may be set and saved in the private system properties in the
         * jdk.internal.misc.VM class.
         *
         * WARNING: The cache is archived with CDS and reloaded from the shared
         * archive at runtime. The archived cache (Integer[]) and Integer objects
         * reside in the closed archive heap regions. Care should be taken when
         * changing the implementation and the cache array should not be assigned
         * with new Integer object(s) after initialization.
         */
    
        private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer[] cache;
            static Integer[] archivedCache;
    
            static {
                // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                if (integerCacheHighPropValue != null) {
                    try {
                        h = Math.max(parseInt(integerCacheHighPropValue), 127);
                        // Maximum array size is Integer.MAX_VALUE
                        h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
                    } catch( NumberFormatException nfe) {
                        // If the property cannot be parsed into an int, ignore it.
                    }
                }
                high = h;
    
                // Load IntegerCache.archivedCache from archive, if possible
                CDS.initializeFromArchive(IntegerCache.class);
                int size = (high - low) + 1;
    
                // Use the archived cache if it exists and is large enough
                if (archivedCache == null || size > archivedCache.length) {
                    Integer[] c = new Integer[size];
                    int j = low;
                    for(int i = 0; i < c.length; i++) {
                        c[i] = new Integer(j++);
                    }
                    archivedCache = c;
                }
                cache = archivedCache;
                // range [-128, 127] must be interned (JLS7 5.1.7)
                assert IntegerCache.high >= 127;
            }
    
            private IntegerCache() {}
        }
    
        /**
         * Returns an {@code Integer} instance representing the specified
         * {@code int} value.  If a new {@code Integer} instance is not
         * required, this method should generally be used in preference to
         * the constructor {@link #Integer(int)}, as this method is likely
         * to yield significantly better space and time performance by
         * caching frequently requested values.
         *
         * This method will always cache values in the range -128 to 127,
         * inclusive, and may cache other values outside of this range.
         *
         * @param  i an {@code int} value.
         * @return an {@code Integer} instance representing {@code i}.
         * @since  1.5
         */
        @IntrinsicCandidate
        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
  • 생성자에 있는 로직을 정적 팩토리 메서드로 캡슐화할 수 있다.
    class User{
    	
    	public User() {
    		doTask1();
    		doTask2();
    		doTask3();
    	}
    }
    생성자에 위치한 일련의 작업들을 정적 팩토리 메서드로 캡슐화 하는 것이다.

공부 : 토비의 스프링 6장

팩토리 빈

Proxy 의 newProxyInstance() 메소드를 통해서만 생성이 가능한 다이나믹 프록시 오브젝트는 일반적인 방법으로는 스프링의 빈으로 등록할 수 없다.

프록시 팩토리 빈

장점

  • 데코레이터 패턴의 단점 2가지 해결
    • 인터페이스 구현하는 프록시 클래스 일일이 생성 번거로움 제거
    • 부가기능 코드의 중복
  • DI 적용한 팩토리 빈은 다이나믹 프록시 생성코드 제거 해준다.
  • 다양한 타깃 오브젝트에 적용 가능

한계

  • 부가기능 제공은 메서드 단위
  • 하나의 타깃에 여러 부가기능 제공시 문제점
    • 설정파일 복잡해진다.
    • InvocationHandler 구현체가 프록시 팩토리 빈 개수만큼 만들어진다.
      → 같은 부가기능을 하는 핸들러라도 타깃 오브젝트 개수 만큼 생성되어야 한다.

개선 : 스프링의 추상화된 프록시 팩토리 빈

ProxyFactoryBean

  • Advice

    타깃 오브젝트에 적용하는 부가기능을 담은 오브젝트를 스프링에서는 어드바이스라고 부른다.
    타깃 오브젝트에 종속되지 않는 순수한 부가기능을 담은 오브젝트다.

  • PointCut

    메서드의 이름을 가지고 부가기능을 적용 대상 메서드를 선정한다.

  • Advisor
    어드바이스와 포인트컷을 묶은 오브젝트를 인터페이스 이름을 따서 어드바이저라고 부른다.

어드바이스와 포인트컷의 재사용

  • ProxyFactoryBean 은 스프링의 DI 템플릿/콜백 패턴, 서비스 추상화 등의 기법이 모두 적용됨.
  • 독립적이고, 여러 프록시가 공유할 수 있는 어드바이스와 포인트컷으로 확장 기능을 분리할 수 있다.

BeanPostProcessor

  • 변하지 않는 핵심적인 부분외에는 대부분 확장할 수 있도록 확장 포인트를 제공해준다.
  • 자동 프록시 생성기

    Factory hook that allows for custom modification of new bean instances
    for example, checking for marker interfaces or wrapping beans with proxies.

  • 컨테이너 초기화 시점에서 자동으로 프록시를 만들어주는 방법을 도입

AOP?

  • 트랜잭션 경계설정과 같은 부가 기능을 객체지향의 오브젝트와는 다른 관점으로 접근을 시도했다.
    그것이 바로 Aspect 다.
  • Aspect 는 애플리케이션의 핵심기능을 담고 있지는 않지만, 애플리케이션을 구성하는 중요한 한 요소이고, 핵심기능에 부가되어 의미를 갖는 특별한 모듈을 뜻한다.
  • 설계와 개발시에 다른 특성을 띤 애스펙트들은 독립적인 관점으로 작성
  • 런타임 시에는 Aspect들은 자기가 필요한 위치에 다이나믹하게 참여
  • 정의 : 애플리케이션을 특정한 관점을 기준으로 바라볼 수 있게 해준다는 의미에서 관점 지향 프로그래밍이라 한다.

AOP 적용 기술

  1. 프록시 이용
  2. 바이트코드 생성과 조작 이용

0개의 댓글