에이전트 모드 - 정적 에이전트 에서 동적 에이전트 로 의 진화 과정

27663 단어 디자인 모드
대리 모델 인터넷 에 커 다란 기술 게시 물이 있 는데 여 기 는 너무 많은 논술 을 하지 않 습 니 다.
프 록 시 모드 전송 도 어
다음은 정적 에이전트 에서 동적 에이전트 로 한 걸음 한 걸음 진화 한다.
먼저 정적 에이전트 의 인 스 턴 스 를 작성 합 니 다:
우선 subject (추상 적 인 주제 역할): IUserService
package com.soft.day1103.dao;

import com.soft.test.model.User;

import java.util.List;

public interface IUserService {

    List findAllUser();

    User findUserById(String id);

    int add(User user);
}

realSubject 실제 테마 캐릭터 UserServiceImpl
package com.soft.day1103.dao.impl;

import com.soft.day1103.dao.IUserService;
import com.soft.test.model.User;

import java.util.ArrayList;
import java.util.List;

public class UserServiceImpl implements IUserService {
    @Override
    public List findAllUser() {
        System.out.println("         ");

        return new ArrayList();
    }

    @Override
    public User findUserById(String id) {
        System.out.println("  id" + id + "        ");
        return new User();
    }

    @Override
    public int add(User user) {
        System.out.println("    ");
        return 0;
    }
}
proxy 에이전트 테마 역할 UserServiceStaticProxy
package com.soft.day1103.proxy;

import com.soft.day1103.dao.IUserService;
import com.soft.day1103.dao.impl.UserServiceImpl;
import com.soft.test.model.User;

import java.util.List;

public class UserServiceStaticProxy implements IUserService {

    //          
    private UserServiceImpl userService = new UserServiceImpl();

    /*           start*/
    /**
     *           
     * @param methodName
     */
    private void pre(String methodName){
        System.out.println(methodName + "    ");
    }

    /**
     *             
     * @param methodName
     */
    private void after(String methodName){
        System.out.println(methodName + "    ");
    }
    /*         end*/

    @Override
    public List findAllUser() {

        pre("findAllUser");
        List list = userService.findAllUser();
        after("findAllUser");
        return list;
    }

    @Override
    public User findUserById(String id) {
        pre("findUserById");
        User user = userService.findUserById(id);
        after("findUserById");
        return user;
    }

    @Override
    public int add(User user) {
        pre("add");
        int addRes = userService.add(user);
        after("add");
        return addRes;
    }
}

실체 클래스: (테스트 용 무의미)
package com.soft.day1103.model;

public class User {


    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

테스트 에이전트 클래스
package com.soft.day1103.proxy;

import com.soft.day1103.dao.IUserService;
import com.soft.test.model.User;
import org.junit.Test;

public class UserServiceStaticProxyTest {

    private IUserService userService = new UserServiceStaticProxy();

    @Test
    public void findAllUser() throws Exception {
        userService.findAllUser();
        print();
    }

    @Test
    public void findUserById() throws Exception {
        userService.findUserById("111");
        print();
    }

    @Test
    public void add() throws Exception {
        userService.add(new User());
        print();
    }

    private void print(){
        System.out.println("=====================================");
    }
}

테스트 결과:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
그 결과 실제 대상 이 되 는 방법 을 실행 할 때마다 프 록 시 논 리 를 삽입 하 는 것 은 프 록 시 성공 을 설명 하 는 것 으로 나 타 났 다.그러나 정적 에이전트 에 단점 이 있 습 니 다.
모든 실제 주제 캐릭터 는 반드시 하나의 대리 류 가 있어 야 한다.즉, 주제 캐릭터 가 하나 더 있 으 면 대리 류 가 하나 더 있어 야 한 다 는 것 이다.류 의 팽창 을 야기 할 수 있다.
지금 customer ServiceImpl 은 대리 가 필요 합 니 다. 이 럴 때 대리 류 를 만들어 야 합 니 다.
package com.soft.day1103.proxy;

import com.soft.day1103.dao.ICustomerService;
import com.soft.day1103.dao.impl.CustomerServiceImpl;
import com.soft.day1103.model.Customer;

import java.util.List;

public class CustomerServiceStaticProxy implements ICustomerService {

    //          
    private ICustomerService userService = new CustomerServiceImpl();

    /*           start*/

    /**
     *           
     *
     * @param methodName
     */
    private void pre(String methodName) {
        System.out.println(methodName + "    ");
    }

    /**
     *             
     *
     * @param methodName
     */
    private void after(String methodName) {
        System.out.println(methodName + "    ");
    }
    /*         end*/

    @Override
    public List findAllCustomer() {

        pre("findAllUser");
        List list = userService.findAllCustomer();
        after("findAllUser");
        return list;
    }

    @Override
    public Customer findUserById(String id) {
        pre("findUserById");
        Customer user = userService.findUserById(id);
        after("findUserById");
        return user;
    }

    @Override
    public int add(Customer user) {
        pre("add");
        int addRes = userService.add(user);
        after("add");
        return addRes;
    }
}
두 개의 정적 대리 류 를 관찰 한 결과 최적화 항목 을 발견 할 수 있다. 모든 방법 이 실행 전후의 코드 가 중복 되 고 공공 부분 으로 추출 할 수 있 지만 집행 방법 이 다 르 기 때문에 이 럴 때 반사 로 방법 을 집행 한 다음 에 반사 집행 방법 전에 대리 논리 처 리 를 할 수 있다.최 적 화 된 코드 를 통 해:
 
  
package com.soft.day1103.proxy;

import com.soft.day1103.dao.IUserService;
import com.soft.day1103.dao.impl.UserServiceImpl;
import com.soft.test.model.User;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

public class UserServiceStaticProxy implements IUserService {

    //          
    private UserServiceImpl userService = new UserServiceImpl();

    /*           start*/
    /**
     *           
     * @param methodName
     */
    private void pre(String methodName){
        System.out.println(methodName + "    ");
    }

    /**
     *             
     * @param methodName
     */
    private void after(String methodName){
        System.out.println(methodName + "    ");
    }
    /*         end*/

    @Override
    public List findAllUser() {
        return (List)excute("findAllUser",new Object[]{},null);
    }

    @Override
    public User findUserById(String id) {
        return (User)excute("findUserById",new Object[]{id},String.class);
    }

    @Override
    public int add(User user) {

        return (int)excute("add",new Object[]{user},User.class);
    }


    private Object excute(String methodName, Object[] param, Class... params){
        Object obj = null;
        try {
            Method method = userService.getClass().getMethod(methodName, params);
            pre(methodName);
            obj = method.invoke(userService,param);
            after(methodName);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return obj;
    }

}
이렇게 최적화 한 후에 테스트 를 한다.
 
  
add    
    
add    
=====================================
findAllUser    
         
findAllUser    
=====================================
findUserById    
  id111        
findUserById    
=====================================
   CustomerServiceStaticProxy           。
 
  
package com.soft.day1103.proxy;

import com.soft.day1103.dao.IUserService;
import com.soft.day1103.dao.impl.UserServiceImpl;
import com.soft.test.model.User;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

public class UserServiceStaticProxy implements IUserService {

    //          
    private UserServiceImpl userService = new UserServiceImpl();

    /*           start*/
    /**
     *           
     * @param methodName
     */
    private void pre(String methodName){
        System.out.println(methodName + "    ");
    }

    /**
     *             
     * @param methodName
     */
    private void after(String methodName){
        System.out.println(methodName + "    ");
    }
    /*         end*/

    @Override
    public List findAllUser() {
        return (List)excute("findAllUser",new Object[]{},null);
    }

    @Override
    public User findUserById(String id) {
        return (User)excute("findUserById",new Object[]{id},String.class);
    }

    @Override
    public int add(User user) {

        return (int)excute("add",new Object[]{user},User.class);
    }


    private Object excute(String methodName, Object[] param, Class... params){
        Object obj = null;
        try {
            Method method = userService.getClass().getMethod(methodName, params);
            pre(methodName);
            obj = method.invoke(userService,param);
            after(methodName);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return obj;
    }

}
对比两个静态代理类,还是有可以提取出来的部分,excute方法可以再次做拆分处理,放到一个共通处理类里面去。 
  
      
 
  
package com.soft.day1103.proxy;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class InvokeHandler {

    /**
     *        
     */
    private Object obj;

    public InvokeHandler(Object obj) {
        this.obj = obj;
    }

    /*           start*/
    /**
     *           
     * @param methodName
     */
    private void pre(String methodName){
        System.out.println(methodName + "    ");
    }

    /**
     *             
     * @param methodName
     */
    private void after(String methodName){
        System.out.println(methodName + "    ");
    }
    /*         end*/


    public Object excute(String methodName, Object[] param, Class... params){
        try {
            Method method = obj.getClass().getMethod(methodName, params);
            pre(methodName);
            obj = method.invoke(obj,param);
            after(methodName);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return obj;
    }

}
然后两个静态代理类,的变化比较大 
  
 
  
package com.soft.day1103.proxy;

import com.soft.day1103.dao.IUserService;
import com.soft.day1103.dao.impl.UserServiceImpl;
import com.soft.test.model.User;

import java.util.List;

public class UserServiceStaticProxy implements IUserService {

    //          
    private UserServiceImpl userService = new UserServiceImpl();
    private InvokeHandler handler = new InvokeHandler(userService);

    @Override
    public List findAllUser() {
        return (List) handler.excute("findAllUser", new Object[]{}, null);
    }

    @Override
    public User findUserById(String id) {
        return (User) handler.excute("findUserById", new Object[]{id}, String.class);
    }

    @Override
    public int add(User user) {
        return (int) handler.excute("add", new Object[]{user}, User.class);
    }
}
훨씬 상쾌 해 지 는 지 보고 대리 논 리 를 따로 포장 하고 대리 류 는 대리 논 리 를 호출 합 니 다.
           ,         。           ,        ,          。
           InvokeHandler,               (InvokeHandler)    。
          jdk         InvocationHandler
 
  
package com.soft.day1103.proxy;

import java.lang.reflect.Method;

public interface InvocationHandler {

    public Object invoke(Method method, Object[] param);
}
InvokeHandler
 
  
package com.soft.day1103.proxy;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class InvokeHandler implements InvocationHandler{

    /**
     *        
     */
    private Object obj;

    public InvokeHandler(Object obj) {
        this.obj = obj;
    }

    /*           start*/
    /**
     *           
     * @param methodName
     */
    private void pre(String methodName){
        System.out.println(methodName + "    ");
    }

    /**
     *             
     * @param methodName
     */
    private void after(String methodName){
        System.out.println(methodName + "    ");
    }
    /*         end*/

    @Override
    public Object invoke(Method method, Object[] param) {
        Object object = null;
        try {
            pre(method.getName());
            object = method.invoke(obj,param);
            after(method.getName());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return object;
    }
}
UserServiceStaticProxy
 
  
package com.soft.day1103.proxy;

import com.soft.day1103.dao.IUserService;
import com.soft.test.model.User;

import java.lang.reflect.Method;
import java.util.List;

public class UserServiceStaticProxy implements IUserService {

    //          
    private InvocationHandler handler;

    public UserServiceStaticProxy(InvocationHandler handler) {
        this.handler = handler;
    }

    @Override
    public List findAllUser() {
        return (List) excute("findAllUser", new Object[]{}, null);
    }

    @Override
    public User findUserById(String id) {
        return (User) excute("findUserById", new Object[]{id}, String.class);
    }

    @Override
    public int add(User user) {
        return (int) excute("add", new Object[]{user}, User.class);
    }

    private Object excute(String methodName, Object[] param, Class... params) {
        Object obj = null;
        try {
            Method method = IUserService.class.getMethod(methodName, params);
            obj = handler.invoke(method, param);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return obj;
    }
}
UserServiceStatic Proxy 코드 도 약간 조정 되 었 습 니 다. 이것 은 jdk 동적 에이전트 의 매개 변수 등 과 일치 하기 위해 조정 한 것 이지 만 사상 은 같 습 니 다.
 
  
package com.soft.day1103.proxy;

import com.soft.day1103.dao.IUserService;
import com.soft.day1103.dao.impl.UserServiceImpl;
import com.soft.test.model.User;
import org.junit.Test;

public class UserServiceStaticProxyTest {
    //         ,       。
    private IUserService userServicesss = new UserServiceImpl();
    InvocationHandler handler = new InvokeHandler(userServicesss);
    private IUserService userService = new UserServiceStaticProxy(handler);

    @Test
    public void findAllUser() throws Exception {
        userService.findAllUser();
        print();
    }

    @Test
    public void findUserById() throws Exception {
        userService.findUserById("111");
        print();
    }

    @Test
    public void add() throws Exception {
        userService.add(new User());
        print();
    }

    private void print(){
        System.out.println("=====================================");
    }
}
우선 에이전트 가 필요 한 클래스 를 실례 화하 고 에이전트 가 필요 한 클래스 를 에이전트 논리 클래스 Invocation Handler 에 넣 고,
  InvocationHandler        
            。
 
  
add    
    
add    
=====================================
findAllUser    
         
findAllUser    
=====================================
findUserById    
  id111        
findUserById    
=====================================
     。
              ,         ,                          ?
       ,              ,         。

Proxy
 
  
package com.soft.day1103.proxy;

import com.soft.day1103.util.ClassMaker;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Proxy {

    public static Object newProxyInstance(Class cla, InvocationHandler handler){
        Class createClass = ClassMaker.createProxyClass(cla);
        try {
            Constructor constructor = createClass.getConstructor(InvocationHandler.class);
            return constructor.newInstance(handler);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }
}
클래스 생 성기 ClassMaker
 
  
package com.soft.day1103.util;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;

public class ClassMaker {

    private static final String IMPORT = "import ";
    private static final String FENHAO = ";
"; private static final String CLASS_PUBLIC = "public class "; private static final String IMPLEMANT = " implements "; private static final String QIANKUOHAO = "{"; private static final String HOUKUOHAO = "}"; private static final String PRIVATE_ = "private "; private static final String PUBLIC = "public "; private static final String NEWLINE = "
"; public static Class classLoad(String classInfo, String className) { try { FileOutputStream fo = new FileOutputStream("D:\\myproject\\mybatisLearn\\src\\main\\java\\com\\soft\\day1103\\proxy\\" + className + ".java"); fo.write(classInfo.getBytes()); fo.flush(); Thread.sleep(1000); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } Class retu = null; try { retu = Class.forName("com.soft.day1103.proxy." + className); } catch (ClassNotFoundException e) { e.printStackTrace(); } return retu; } public static Class createProxyClass(Class targetObject) { StringBuffer sb = new StringBuffer(); sb.append("package com.soft.day1103.proxy;"); sb.append("import java.lang.reflect.Method;"); String interfaceName = targetObject.getSimpleName(); sb.append("import " + targetObject.getPackage().getName() +"."+ interfaceName + ";"); Method[] methods = targetObject.getMethods(); for (Method method : methods) { Class returnType = method.getReturnType(); if(needImport(returnType)){ sb.append("import " + returnType.getPackage().getName() +"."+ returnType.getSimpleName() + ";"); } } // sb.append(" public class " + interfaceName + "Proxy implements " + interfaceName + " {"); // sb.append("private InvocationHandler handler;"); // sb.append("public " + interfaceName + "Proxy(InvocationHandler handler) {"); sb.append("this.handler = handler;}"); // for (Method method : methods) { Class returnType = method.getReturnType(); Class[] methodParamClass = method.getParameterTypes(); sb.append("@Override" + NEWLINE); sb.append(PUBLIC + returnType.getName() + " " + method.getName() + "("); // StringBuffer refMethodParamters = new StringBuffer(); int index = 0; // StringBuffer methodParams = new StringBuffer(); // class StringBuffer refMethodClasses = new StringBuffer(); for (Class methodParam : methodParamClass) { String paramName = methodParam.getName(); methodParams.append(paramName + " param" + index + ","); refMethodParamters.append(" param" + index + ","); String[] arr = paramName.split("\\."); refMethodClasses.append(arr[arr.length - 1] + ".class" + ","); index++; } if (methodParams.length() > 0) { sb.append(methodParams.substring(0, methodParams.toString().length() - 1)); } sb.append(")" + QIANKUOHAO + NEWLINE); if (refMethodParamters.length() > 0) { sb.append("Object[] objects = { " + refMethodParamters.substring(0, refMethodParamters.length() - 1) + "}" + FENHAO + NEWLINE); } else { sb.append("Object[] objects = new Object[" + methodParamClass.length + "]" + FENHAO + NEWLINE); } if (needReturn(returnType)) { sb.append("return (" + returnType.getName() + ")"); } String classes = null; if(refMethodClasses.length() > 0){ classes = refMethodClasses.substring(0,refMethodClasses.length()-1); } sb.append("excute(\"" + method.getName() + "\" , objects , " + classes + ")" + FENHAO + NEWLINE); sb.append(HOUKUOHAO + NEWLINE); } // sb.append(" private Object excute(String methodName, Object[] param, Class... params) {"); sb.append("Object obj = null;"); sb.append("try {"); sb.append("Method method = " + interfaceName + ".class.getMethod(methodName, params);"); sb.append("obj = handler.invoke(method, param);"); sb.append("} catch (NoSuchMethodException e) {"); sb.append(" e.printStackTrace();}"); sb.append("return obj;}"); sb.append(HOUKUOHAO + FENHAO + NEWLINE); return classLoad(sb.toString(), interfaceName + "Proxy"); } private static boolean needImport(Class tar) { return "voidStringintdoublelangfloatbooleanbytecharshort".indexOf(tar.getSimpleName()) == -1; } private static boolean needReturn(Class tar) { return "void".indexOf(tar.getSimpleName()) == -1; } }
현재 동적 에이전트 테스트 를 진행 하고 있 습 니 다.대 리 를 동적 으로 실현 할 수 있 는 지 확인 하 다.
       ,     java           。       ,        java  。           。

      :
       IUserService
 
  
 @Test
    public void testproxy() throws Exception {
        IUserService iUserService = (IUserService)Proxy.newProxyInstance(IUserService.class, handler);
        iUserService.add(new User());
        print();
    }
테스트 결과:
add    
    
add    
=====================================
       ICustomerService
 
  
    @Test
    public void testproxy() throws Exception {
        ICustomerService iUserService = (ICustomerService)Proxy.newProxyInstance(ICustomerService.class, handler);
        iUserService.add(new Customer());
        print();
    }
테스트 결과:
add    
    
add    
=====================================
 
  
              。     。

           :
 
  
package com.soft.day1103.proxy;

import java.lang.reflect.Method;

import com.soft.day1103.dao.IUserService;

import java.util.List;

import com.soft.test.model.User;

public class IUserServiceProxy implements IUserService {
    private InvocationHandler handler;

    public IUserServiceProxy(InvocationHandler handler) {
        this.handler = handler;
    }

    @Override
    public int add(com.soft.test.model.User param0) {
        Object[] objects = {param0};

        return (int) excute("add", objects, User.class);

    }

    @Override
    public java.util.List findAllUser() {
        Object[] objects = new Object[0];

        return (java.util.List) excute("findAllUser", objects, null);

    }

    @Override
    public com.soft.test.model.User findUserById(java.lang.String param0) {
        Object[] objects = {param0};

        return (com.soft.test.model.User) excute("findUserById", objects, String.class);

    }

    private Object excute(String methodName, Object[] param, Class... params) {
        Object obj = null;
        try {
            Method method = IUserService.class.getMethod(methodName, params);
            obj = handler.invoke(method, param);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return obj;
    }
};
package com.soft.day1103.proxy;

import com.soft.day1103.dao.ICustomerService;
import com.soft.day1103.model.Customer;

import java.lang.reflect.Method;

public class ICustomerServiceProxy implements ICustomerService {
    private InvocationHandler handler;

    public ICustomerServiceProxy(InvocationHandler handler) {
        this.handler = handler;
    }

    @Override
    public int add(com.soft.day1103.model.Customer param0) {
        Object[] objects = {param0};

        return (int) excute("add", objects, Customer.class);

    }

    @Override
    public java.util.List findAllCustomer() {
        Object[] objects = new Object[0];

        return (java.util.List) excute("findAllCustomer", objects, null);

    }

    @Override
    public com.soft.day1103.model.Customer findUserById(java.lang.String param0) {
        Object[] objects = {param0};

        return (com.soft.day1103.model.Customer) excute("findUserById", objects, String.class);

    }

    private Object excute(String methodName, Object[] param, Class... params) {
        Object obj = null;
        try {
            Method method = ICustomerService.class.getMethod(methodName, params);
            obj = handler.invoke(method, param);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return obj;
    }
};

좋은 웹페이지 즐겨찾기