spring 04 aop_대리

정적 에이전트
특징:
  • 목표 대상 은 인 터 페 이 스 를 실현 해 야 한다
  • 대리 대상, 목표 대상 과 같은 인터페이스 실현
  • * 수요: * UserDao. java dao 인터페이스 UserDaoImpl. java dao 구현 (대상) void save (); /UserDaoProxy. java dao 프 록 시 클래스 를 저장 하여 UserDao 의 기능 을 확장 합 니 다!(에이전트 대상) 앱
    단점:
  • 대리 대상, 목표 대상 의 인터페이스 에 의존 해 야 합 니 다!인터페이스 기능 변화, 목표 대상 변화, 대리 대상 변화 도입!
  • 모든 목표 대상 에 대해 각각 대리 류 를 써 야 합 니 다. 귀 찮 습 니 다!(단 대리 공장 사용 가능)
  • 클래스:
    public interface UserDao {
        public void save();
    }
    
    public class UserDaoImpl implements UserDao {
        public void save(){
            System.out.println("    ");
        }
    }
    
    public class UserDaoProxy implements UserDao{
        private UserDao userDao = new UserDaoImpl();
        public void save(){
            System.out.println("    ......");
            userDao.save();
            System.out.println("    ......");
        }
    }
    
    public class App {
        
        @Test
        public void test(){
            UserDao proxy = new UserDaoProxy();
            proxy.save();
        }
    }
    

    동적 에이전트
  • 흔히 말 하 는 동적 대 리 는 jdk 대 리 를 말 합 니 다!jdk 의 api 를 통 해 실행 시기 에 동적 으로 프 록 시 대상 을 생 성 했 기 때 문 입 니 다!
  • 목표 대상 은 반드시 인 터 페 이 스 를 실현 해 야 한다. 대리 대상 은 인 터 페 이 스 를 실현 하지 않 아 도 된다!

  • JDK 가 프 록 시 대상 을 만 드 는 Api (Proxy)
    static Object
    newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) 
    

    매개 변수 loader: 현재 대상 이 사용 하 는 클래스 로 더!
    매개 변수 interfaces: 현재 대상 이 실현 하 는 인터페이스
    인자 h: 인터페이스 형식, 이벤트 프로세서. 대상 방법 을 실행 할 때 이벤트 가 발생 합 니 다.현재 실행 중인 방법 (method 대상) 을 이벤트 프로세서 방법 파라미터 에 전송 하면 업무 논리 에 따라 목표 대상 방법 이나 확장 기능 을 실행 할 지 여 부 를 판단 할 수 있 습 니 다!
    종류
    public interface UserDao {
        public void save();
        public void find();
    }
    
    public class UserDaoImpl implements UserDao {
        public void save(){
            System.out.println("    ");
        }
        
        public void find(){
            System.out.println("    ");
        }
    }
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyFactory {
        
        private Object target; //    
        public ProxyFactory(Object target){
            this.target = target;
        }   
        
        public Object getProxyInstance(){
            Object proxy = Proxy.newProxyInstance(
                    target.getClass().getClassLoader(), 
                    target.getClass().getInterfaces(),
                    new InvocationHandler(){
    
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            Object result = null;
                            if(method.getName().equals("save")){
                                System.out.println("    ");
                                result = method.invoke(target, args);
                                System.out.println("    ");
                            }else{
                                result = method.invoke(target, args);
                            }
                                
                            return result;
                        }
                        
                    }
                );
            return proxy;
        }
    }
    
    public class App {
        
        @Test
        public void test(){
            //      
            UserDaoImpl userDaoImpl = new UserDaoImpl();
            UserDao proxy = (UserDao) new ProxyFactory(userDaoImpl).getProxyInstance();
            /*                 ;          */
            
            proxy.save();
        }
    }
    
    

    cglib 에이전트
    '하위 에이전트' 라 고도 부 릅 니 다. 목표 대상 이 인 터 페 이 스 를 실현 하지 않 으 면 jdk 가 제공 하 는 대 리 를 사용 할 수 없고 하위 클래스 로 실현 할 수 있 습 니 다!실행 시기 에 동적 으로 메모리 에 하위 클래스 대상 을 구축 하 는 방법 으로 대상 을 확장 합 니 다. 이것 이 바로 cglib 에이전트 입 니 다!Spring 도 cglib 에이 전 트 를 지원 합 니 다. 핵심 패키지 에 이 기능 이 포함 되 어 있 습 니 다!
  • JDK 의 동적 에이 전 트 는 동적 에이 전 트 를 사용 하 는 대상 이 하나 이상 의 인 터 페 이 스 를 실현 해 야 한 다 는 제한 이 있다.인 터 페 이 스 를 구현 하지 못 한 클래스 를 대리 하려 면 CGLIB 를 사용 하면 된다.
  • CGLIB 는 강력 한 고성능 코드 생 성 패키지 로 실행 기간 에 자바 류 를 확장 하고 자바 인 터 페 이 스 를 실현 할 수 있다.그것 은 많은 AOP 의 프레임 워 크 에 광범 위 하 게 사용 되 고 있 습 니 다. 예 를 들 어 Spring AOP 와 dynaop 은 그들 에 게 방법 을 제공 하 는 interception (차단) 입 니 다.
  • CGLIB 패키지 의 밑바닥 은 작고 빠 른 바이트 처리 프레임 ASM 을 사용 하여 바이트 코드 를 변환 하고 새로운 클래스 를 생 성 한다.ASM 을 직접 사용 하 는 것 을 권장 하지 않 습 니 다. JVM 내부 구조 가 class 파일 을 포함 한 형식 과 명령 집합 에 대해 잘 알 아야 하기 때 문 입 니 다.

  • 요약:
  • 목표 대상 은 인터페이스
  • 를 실현 하지 않 을 수 있다.
  • 목표 류 는 final 이 될 수 없고 final 이 잘못 되면
  • 방법 이 final / static 이면 대리 에 의 해 차단 되 지 않 습 니 다!목표 대상 방법 을 직접 수행 합 니 다!

  • 클래스:
    public class UserDao {
        public void save(){
            System.out.println("  save");
        }
        public void find(){
            System.out.println("  find");
        }
    }
    
    import java.lang.reflect.Method;
    
    import org.springframework.cglib.proxy.Callback;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.InvocationHandler;
    
    public class ProxyFactory implements InvocationHandler{
        
        private Object target; //    
        public ProxyFactory(Object target){
            this.target = target;
        }   
        
        //             
        public Object getProxyInstance(){
            //        
            Enhancer enhancer = new Enhancer();
            //    
            enhancer.setSuperclass(target.getClass());//        
            //      
            enhancer.setCallback((Callback) this);
            return enhancer.create();
        }
    
        
    
        @Override
        public Object invoke(Object arg0, Method method, Object[] args) throws Throwable {
            Object result = null;
            if(method.getName().equals("save")){
                System.out.println("    ");
                result = method.invoke(target, args);
                System.out.println("    ");
                
            }else{
                
                result = method.invoke(target, args);
            }
            
            return result;
        }
    }
    
    
    public class App {
        
        @Test
        public void test(){
            //      
            UserDao userDao = new UserDao();
            UserDao proxy = (UserDao) new ProxyFactory(userDao).getProxyInstance();
            /*                 ;          */
            
            proxy.save();
            proxy.find();
        }
    }
    

    좋은 웹페이지 즐겨찾기