에이전트 디자인 패턴 노트

프록시 모드 : 해결해야 할 주요 문제는 특정 리소스에 대한 액세스와 사용하기 쉬운 객체 클래스 작업을위한 편리한 프록시 서비스를 제공하는 것입니다.

사용할 장면 :

  1. 서비스 확장 중 데이터베이스 연결 수의 갑작스런 증가를 줄이기 위해 데이터베이스 액세스 수준을 통해보다 기본적인 애플리케이션을 제공합니다.
  2. 일부 미들웨어 : RPC 프레임 워크. jar 패키지의 인터페이스 설명을 얻은 후 미들웨어는 서비스 시작시 해당 프록시 클래스를 생성하고, 인터페이스가 호출되면 소켓 정보가 실제로 프록시 클래스를 통해 전송됩니다.
  3. MyBatis는 기본적으로 인터페이스를 정의하지만 구현 클래스를 작성할 필요가 없으며 mapper.xml이나 Annotation에서 SQL 문을 추가, 삭제, 수정, 확인할 수 있습니다.

구조:

  • 추상 테마 역할 : 실제 테마와 에이전트 테마 간의 공통 인터페이스를 선언합니다.
  • 상담원 테마 역할 : 내부에는 실제 테마 및 상담원 테마에 대한 공통 인터페이스가 포함됩니다.
  • 실제 테마 역할 : 실제 개체를 정의합니다.

 Spring AOP는 동적 프록시 기반입니다 . 프록시 대상 객체가 특정 인터페이스를 구현하면 Spring AOP는 JDK 프록시 를 사용하여 프록시 객체를 생성합니다. 인터페이스를 구현하지 않는 객체의 경우 JDK 프록시를 프록시에 사용할 수 없습니다. 시간은 스프링 AOP가 사용 CGLIB를  이 때, 스프링 AOP가 사용합니다.  하는 CGLIB를  다음 그림과 같이 프록시와 프록시 객체의 하위 클래스를 생성합니다 :

SpringAOPProcess

 물론 AspectJ를 사용할 수도 있습니다. Spring AOP는 AspectJ 를 통합 했으며 AspectJ는 자바 생태계에서 가장 완벽한 AOP 프레임 워크로 간주되어야합니다.

확장-Spring AOP와 AspectJ AOP의 차이점

JDK의 동적 프록시

InvocationHandler中的invoke()方法属于代理类中调用真实主题类的方法,但是该方法没有所对应的真实主题类,需要在创建对象时设置真实主题。

package java.lang.reflect;

public interface InvocationHandler {
    /**
     * Object proxy:代理类的对象[代理后的类]
     * Method method:需要调用的方法
     * Object[] args:方法所需的参数
     */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

 프록시 객체를 가져 오려면 java.lang.reflect.Proxy 클래스를 사용하여 동적으로 생성해야합니다.

/**
 * ClassLoader loader:取得对象的加载器
 * Class<?>[] interfaces:代理模式的核心是围绕接口进行的,所以需取出全部接口
 * InvocationHandler h:代理实现类
public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

 

 예 1 :

// 简单Java类
public class Dept {
}


// 定义的接口层
public interface IDeptDAO {
    boolean doCreate(Dept vo) throws Exception;
    List<Dept> findAll() throws Exception;
}

// 具体接口实现
public class DeptDAOImpl implements IDeptDAO{
    @Override
    public boolean doCreate(Dept vo) throws Exception {
        System.out.println("执行数据增加操作");
        return false;
    }

    @Override
    public List<Dept> findAll() throws Exception {
        System.out.println("执行数据查询操作");
        return null;
    }
}

//动态代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DAOProxy implements InvocationHandler {
    // 不能与具体的DAO耦合在一起
    private Object obj ; // 真实主题类--需要代理的

    /**
     * 将真实主题类绑定到代理中,返回一个被代理后的对象
     * @param obj 真实主题类
     * @return 代理后的对象
     */
    public Object bind(Object obj){

        // !!!!要保存真实主题类--便于后面的方法执行!!!!
        this.obj = obj ;
        /**
         * -----由Java系统实现的代理
         * obj.getClass().getClassLoader() : 通过反射取得该真实主题类的类加载器
         * obj.getClass().getInterfaces() : 通过反射取得真实主题的所有接口
         * this: 由于当前DAOProxy实现了InvocationHandler,所以是代理类
         */
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

    public void prepare(){
        System.out.println("*************取消JDBC的自动提交***************");
    }

    public void commit(){
        System.out.println("*************手动提交JDBC事务***************");
    }

    public void rollback(){
        System.out.println("*************手动回滚JDBC事务***************");
    }

    // 只要执行了方法,就会触发执行invoke()方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null ; // 接收结果
        if (method.getName().contains("do")){
            // 取得方法的名称对操作进行判断
            this.prepare();
            try {
                // 反射中的知识--执行方法需要存在类的实例所以要保存this.obj
                result = method.invoke(this.obj, args);
                this.commit();
            } catch (Exception e){
                e.printStackTrace();
                rollback();
            }
        } else{
            // 如果不需要开启事务,则直接执行方法
            result = method.invoke(this.obj, args);
        }
        return result;
    }
}

// 通过工厂类隐藏具体细节
public class DAOFactory {
    public static Object getDAOInstance(){
        // 直接将真实主题类绑定到代理中返回代理后的类
        return new DAOProxy().bind(new DeptDAOImpl());
    }
}

//测试类
public class ProxyMain {
    public static void main(String[] args) throws Exception{
        IDeptDAO  dao = (IDeptDAO) DAOFactory.getDAOInstance();
        Dept dept = new Dept();
        dao.doCreate(dept);
        dao.findAll();
    }
}

/* output:
 * *************取消JDBC的自动提交***************
 * 执行数据增加操作
 * *************手动提交JDBC事务***************
 * 执行数据查询操作
 * /

CGLIB 동적 에이전트

CGLIB는이 패키지 사용하여 인터페이스없이 동적 프록시 디자인 패턴 구현합니다.

CGLIB는 강력한 고성능 코드 생성 라이브러리입니다. AOP 프레임 워크 (Spring, dynaop)에서 메서드 차단 작업을 제공하기 위해 널리 사용됩니다. 더 많이 사용되는 ORM 프레임 워크 인 Hibernate는 CGLIB를 사용하여 단일 종단 (다 대일 및 일대일) 연결 (지연된 컬렉션에서 사용되는 또 다른 메커니즘)을 프록시합니다.

CGLIB를 사용하는 경우 해당 관계가 명확해야합니다.

  • 프록시-> net.sf.cglib.proxy.Enhancer;
  • InvocationHandler-> net.sf.cglib.proxy.MethodInterceptor;
  • 실제 테마 호출 : net.sf.cglib.proxy.MethodProxy
package 代理设计模式;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

class FunctionImple{
    public void create(){
        System.out.println("create方法");
    }
}
class MyProxy implements MethodInterceptor{
    private Object object; // 真实操作主题类
    public MyProxy(Object object){
        this.object = object;
    }
    public void prepre(){
        System.out.println("取消自动提交");
    }
    public void commit(){
        System.out.println("提交进行事务操作");
    }
    public void rollback(){
        System.out.println("提交失败,回滚");
    }

    
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object reuslt = null;
        // 说明proxy是真实类的子类--如果被代理类是Final类就无法使用CGLIB
        // 但是ASM可以对Final进行代理
        System.out.println(proxy.getClass().getSuperclass().getName());
        this.prepre();
        // CGLIB反射调用真实对象方法
        reuslt = methodProxy.invokeSuper(proxy, args);
        this.commit();
        return reuslt;
    }
}
public class CGLIBDemo {
    public static void main(String[] args) {
        // 真实主题对象
        FunctionImple functionImple = new FunctionImple();
        // CGLIB enhancer增强类对象
        Enhancer enhancer = new Enhancer();
        // 设置增强类型--是当前类的子类
        enhancer.setSuperclass(FunctionImple.class);
        // 定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
        enhancer.setCallback(new MyProxy(functionImple));
        // 生成并返回代理对象
        FunctionImple proxyDao = (FunctionImple) enhancer.create();
        proxyDao.create();

    }
}
/**
 * 代理设计模式.FunctionImple
 * 取消自动提交
 * create方法
 * 提交进行事务操作
 */

 

 

 

추천

출처blog.csdn.net/weixin_39443483/article/details/113803952