动态代理(设计模式)

代理模式概述

     代理模式属于结构型模式,指的是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式包含角色及其职责:

  • 抽象角色[Subject]:通过接口或抽象类声明真实角色待实现方法;
  • 代理角色[Proxy]:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作(可做增强操作);
  • 真实角色[RealSubject]:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用;
  • 代理模式有不同的形式,主要有两种,静态代理、动态代理(静态代理较简单不做介绍)
  • 动态代理分为两种:
    • jdk 动态代理,基于接口;
    • cglib 代理,基于类; 可以在内存中动态的创建对象,而不需要实现接口。

代理模式包含角色及其职责:

设计原则:

  • 隔离原则

    在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到桥梁的作用, 其特征是代理类与委托类有同样的接口。

  • 开闭原则

     代理类不仅仅是一个隔离客户端和委托类的中介。我们还可以借助代理来在增加一些功能,而不需要修改原有代码,严重的符合开闭原则。

代理模式的优点:

  • 公共业务交给代理角色,实现业务的分工。公共业务发生扩展的时无需修改源码,符合开闭原则,系统具有较好的灵活性和可扩展性;
  • 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度;

源码演示:

第一个:jdk动态代理

1、定义接口类

package com.northeasttycoon.proxy.dynamic.proxy;

/**
 * @author :tycoon
 * @date :2018-10-01 9:08
 */
public interface IUserDao {

    void findUserPojo();
}

2、实现接口类

package com.northeasttycoon.proxy.dynamic.proxy;

/**
 * @author :tycoon
 * @date :2018-10-01 9:08
 */
public class UserImpl implements IUserDao {

    @Override
    public void findUserPojo() {
        System.out.println("此方法为jdk动态代理。查询用户信息为:{userID:1001,userName:Northeast Tycoon,alias:Java.Zhao}");

    }
}

3、jdk动态代理实现类

package com.northeasttycoon.proxy.dynamic.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author :tycoon
 * @date :2018-10-01 9:07
 */
public class ProxyInvocationHandler implements InvocationHandler {

    // 需要代理的对象,既:真实对象
    private Object target;

    public void setObject(Object target) {
        this.target = target;
    }


    public Object getProxy() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /*
     * 处理代理对象的方法时会调用此方法
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        // 通过反射实现动态代理,调用真实对象方法
        Object result = method.invoke(target, args);
        after();
        return result;
    }

    //  执行前-增强方法
    public void before() {
        System.out.println(" This is northeasttycoon jdkDynamicProxy,调用动态代理方法前------");
    }
    //  执行后-增强方法
    public void after() {
        System.out.println("This is northeasttycoon jdkDynamicProxy,调用动态代理方法后------"); } }

 

第二个:cglib 动态代理

1、定义目标对象(真实对象)

package com.northeasttycoon.proxy.dynamic.proxy;

/**
 * @author :tycoon
 * @date :2018-10-01 9:10
 */
public class UserDao {

    public void findUserPojo() {
        System.out.println("此方法为CGlib动态代理。查询用户信息为:{userID:1001,userName:Northeast Tycoon,alias:Java.Zhao}");

    }
}

2、cglib 动态代理类

package com.northeasttycoon.proxy.dynamic.proxy;

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

import java.lang.reflect.Method;

/**
 * @author :tycoon
 * @date :2018-10-01 9:28
 */
public class CglibDynamicProxy implements MethodInterceptor {

    //维护一个目标对象
    private Object target;

    //构造器,传入一个被代理的对象
    public CglibDynamicProxy(Object target) {
        this.target = target;
    }

    //返回一个代理对象:  是 target 对象的代理对象
    public Object getProxyInstance() {
        //1. 通过CGLIB动态代理获取代理对象的过程
        Enhancer enhancer = new Enhancer();
        //2. 设置enhancer对象的父类
        enhancer.setSuperclass(target.getClass());
        //3. 设置enhancer的回调对象
        enhancer.setCallback(this);
        //4. 创建子类对象,即代理对象
        return enhancer.create();

    }

    /**
     * 重写  intercept 方法,会调用目标对象的方法
     * @param arg0 cglib生成的代理对象
     * @param method 被代理对象的方法
     * @param args     传入方法的参数
     * @param arg3 代理的方法
     * @return 对象
     * @throws Throwable
     */
    @Override
    public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
        System.out.println("cglib代理模式 ~~ start");
        Object returnVal = method.invoke(target, args);
        System.out.println("cglib代理模式 ~~ end");
        return returnVal;
    }

}

测试类

package com.northeasttycoon.proxy.dynamic.proxy;

import org.junit.jupiter.api.Test;

/**
 * @author :tycoon
 * @date :2018-10-01 9:18
 */
public class TestProxy {

    /**
     * jdk 动态代理实现
     */
    @Test
    public void test01(){
        //需要被代理的对象
        UserImpl userService = new UserImpl();

        //生成代理类
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setObject(userService);
        IUserDao proxy = (IUserDao) pih.getProxy();

        //调用代理类的方法
        proxy.findUserPojo();
    }

    /**
     * cglib的动态代理
     */
    @Test
    public void test02(){

        //创建目标对象
        UserDao target = new UserDao();
        //获取到代理对象,并且将目标对象传递给代理对象
        UserDao proxyInstance = (UserDao)new CglibDynamicProxy(target).getProxyInstance();

        //执行代理对象的方法,触发intecept 方法,实现对目标对象的调用
        proxyInstance.findUserPojo();
    }
}

测试结果:

 

posted @ 2021-10-08 23:55  东北大亨  阅读(53)  评论(0编辑  收藏  举报