动态代理

参考资料

设计模式之禅: https://item.jd.com/10095020247922.html

尚硅谷Java设计模式

静态代理

SysdictService

package com.laolang.bzrj.mybatis.proxy.staticproxy;

public interface SysdictService {

    String selectName();
}

SysdictServiceImpl

package com.laolang.bzrj.mybatis.proxy.staticproxy;

public class SysdictServiceImpl implements SysdictService{
    @Override
    public String selectName() {
        System.out.println("select name");
        return "system_setting";
    }
}

SysdictServiceProxy

package com.laolang.bzrj.mybatis.proxy.staticproxy;

public class SysdictServiceProxy implements SysdictService {

    private final SysdictService target;

    public SysdictServiceProxy(SysdictService target) {
        this.target = target;
    }

    @Override
    public String selectName() {
        System.out.println("pre action");
        String result = target.selectName();
        System.out.println("post action");
        return result;
    }
}

test

package com.laolang.bzrj.mybatis.proxy.staticproxy;

import org.testng.annotations.Test;

public class StaticProxyTest {

    @Test
    public void staticTest() {
        SysdictService target = new SysdictServiceImpl();
        SysdictServiceProxy proxy = new SysdictServiceProxy(target);
        String ret = proxy.selectName();
        System.out.println("ret:" + ret);
    }
}

输出

pre action
select name
post action
ret:system_setting

优缺点

优点: 在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展
缺点: 需要与被代理对象实现相同的接口,需要同事维护被代理对象和代理对象

jdk 代理

SysdictServiceProxyFactory

package com.laolang.bzrj.mybatis.proxy.jdkproxy;

import java.lang.reflect.Proxy;

public class SysdictServiceProxyFactory {
    private final Object target;

    public SysdictServiceProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> {
            System.out.println("pre action");
            Object ret = method.invoke(target, args);
            System.out.println("post action");
            return ret;
        });
    }
}

测试

SysdictServiceSysdictServiceImpl 和上面的一样

package com.laolang.bzrj.mybatis.proxy.jdkproxy;

import org.testng.annotations.Test;

public class JdkProxyTest {

    @Test
    public void jdkTest() {
        SysdictService target = new SysdictServiceImpl();
        SysdictServiceProxyFactory proxyFactory = new SysdictServiceProxyFactory(target);
        SysdictService proxy = (SysdictService) proxyFactory.getProxyInstance();
        String ret = proxy.selectName();
        System.out.println("ret:" + ret);
    }
}

cglib

pom

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

SysdictServiceImpl

package com.laolang.bzrj.mybatis.proxy.cglibproxy;

public class SysdictServiceImpl {
    public String selectName() {
        System.out.println("select name");
        return "system_setting";
    }
}

SysdictServiceProxyFactory

package com.laolang.bzrj.mybatis.proxy.cglibproxy;

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class SysdictServiceProxyFactory implements MethodInterceptor {

    private final Object target;

    public SysdictServiceProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        // 1. 创建工具类
        Enhancer enhancer = new Enhancer();
        // 2. 设置父类
        enhancer.setSuperclass(target.getClass());
        // 3. 设置回调函数
        enhancer.setCallback(this);
        // 4. 创建子类对象, 即代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("pre action");
        Object ret = method.invoke(target, args);
        System.out.println("post action");
        return ret;
    }
}

test

package com.laolang.bzrj.mybatis.proxy.cglibproxy;

import org.testng.annotations.Test;

public class CglibProxyTest {

    @Test
    public void cgligTest(){
        SysdictServiceImpl target = new SysdictServiceImpl();
        SysdictServiceProxyFactory proxyFactory = new SysdictServiceProxyFactory(target);
        SysdictServiceImpl proxy = (SysdictServiceImpl) proxyFactory.getProxyInstance();
        String ret = proxy.selectName();
        System.out.println("ret:" + ret);
    }
}

注意

  1. cglib 不能代理 final 修饰的 class
  2. cglib 不能拦截 finalstatic 修饰的方法
posted @ 2024-08-08 07:44  潼关路边的一只野鬼  阅读(4)  评论(0编辑  收藏  举报