栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

动态代理设计模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

动态代理设计模式

参考资料:

1.重学设计模式书籍

2.https://www.cnblogs.com/tera/p/13911819.html

3.参考 :http://www.mayikt.com/front/couinfo/194/0

设计模式代理设计模式Proxy 1.代理模式

代理模式控制对象的行为,

对对象行为增加(装饰者模式也可以对象的行为进行增加).属于结构行模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qUTG66dk-1635928910217)(…jdk-proxyimg1.png)]

通俗来说,就是我想点份外卖,但是手机没电了,于是我让同学用他手机帮我点外卖。在这个过程中,其实就是我同学(代理对象)帮我(被代理的对象)代理了点外卖(被代理的行为),在这个过程中,同学可以完全控制点外卖的店铺、使用的APP,甚至把外卖直接吃了都行**(对行为的完全控制)**。

2.JDK代理基本实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CKnwdOfg-1635928910221)(…jdk-proxyimg3.png)]

JDK动态代理, 静态代理需要自己编写代理类。

public interface AbStractSubject {

    String showInfo();
}
public class SubjectImpl implements AbStractSubject{
    @Override
    public String showInfo() {
        return "jdk动态代理技术基本使用";
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class JdkInvocationHandler implements InvocationHandler {
    
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始执行前系统当前时间:" + System.currentTimeMillis());
        Object invoke = method.invoke(target, args);//返回执行目标方法的返回值
        System.out.println("执行结果:" + invoke);
        System.out.println("结束执行后系统的时间" + System.currentTimeMillis());
        return invoke;
    }


    
    public  T getProxy() {
        //loader – 定义代理类的类加载器
		//接口 - 代理类要实现的接口列表
		//h – 将方法调用分派到的调用处理程序
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}

public class JDKProxyTest {
    public static void main(String[] args) {
        AbStractSubject  abStractSubject = new JdkInvocationHandler(new SubjectImpl()).getProxy();
        abStractSubject.showInfo();
    }
}

JDK动态代理的另一种写法

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


public class JdkProxy {
    
    private Object target;

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

    
    public  T getProxyObj() {
        InvocationHandler handler = (proxy, method, args) -> {
            System.out.println("1.方法前执行~~~~~");
            Object invoke = method.invoke(target, args);
            if (invoke != null) {
                System.out.println(invoke);
            }
            System.out.println("2.方法后执行~~~~~~");
            return invoke;
        };
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), handler);
    }
}

public class JDKProxyTest2 {
    public static void main(String[] args) {
        AbStractSubject proxyObj = new JdkProxy(new SubjectImpl()).getProxyObj();

        proxyObj.userInfo();
        System.out.println("-------------------------------");
        proxyObj.showInfo();
    }
}
3.案例场景模拟
  • 使⽤过的⼀些中间件例如;RPC框架,在拿到jar包对接⼝的描述后,中间件会在服务启动的时候⽣成对应的代理类,当调⽤接⼝的时候,实际是通过代理类发出的socket信息进⾏通过
  • 另外像我们常⽤的 MyBatis ,基本是定义接⼝但是不需要写实现类,就可以对 xml 或者⾃定义注解⾥的 sql 语句进⾏增删改查操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-04FhXy6S-1635928910224)(…jdk-proxyimg2.png)]

3.1 代理类模式实现Mapper代理
import com.example.proxy.anotaion.Select;

public interface IUserDao {
 @Select("select * from mayikt_type where id = #{uId}")
 String queryUserInfo(String uId);
}
import com.example.proxy.anotaion.Select;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;

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


public class MapperFactoryBean implements FactoryBean {
    private Logger logger =  LoggerFactory.getLogger(MapperFactoryBean.class);
    private Class mapperInterface;

    public MapperFactoryBean(Class mapperInterface) {
        this.mapperInterface = mapperInterface;
    }

    @Override
    public T getObject() throws Exception {
        InvocationHandler handler = (proxy, method, args) -> {
            Select select = method.getAnnotation(Select.class);
            logger.info("SQL:{}", select.value().replace("#{uId}", args[0].toString()));
            return args[0] + ",沉淀、分享、成⻓,让⾃⼰和他 ⼈都能有所收获!";
        };
        return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]
                        {mapperInterface}, handler);
    }

    @Override
    public Class getObjectType() {
        return mapperInterface;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
import com.example.proxy.mapper.IUserDao;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;


public class RegisterBeanFactory implements BeanDefinitionRegistryPostProcessor {

    
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(MapperFactoryBean.class);
        beanDefinition.setScope("singleton");

        beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(IUserDao.class);
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(beanDefinition, "userDao");
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { }
}


    

@SpringBootTest

class MayiktProxyDemoApplicationTests {
    Logger logger = LoggerFactory.getLogger(MayiktProxyDemoApplicationTests.class);


    @Test
    void contextLoads() {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
        IUserDao userDao = beanFactory.getBean("userDao", IUserDao.class);
        String res = userDao.queryUserInfo("1");
        logger.info("测试结果:{}", res);
    }

}

SpringAop 中使用jdk代理和cglib代理, 被代理类实现抽象主题接口实现接口 采用的是jdk代理; 被代理类继承抽象的主题角色采用cglib代理

3.2 对接口方法代理

在一些rpc框架中,客户端只需要关注接口的的调用,而具体的远程请求则由框架内部实现。

public interface OrderInterface {
   
   void addOrder(String name);
}
import com.example.proxy.util.HttpClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class SimpleRpcframe {

    Logger logger = LoggerFactory.getLogger(SimpleRpcframe.class);

    
    public static  T getRemoteProxy(Class service) {
        return (T) Proxy.newProxyInstance(service.getClassLoader(),
                new Class[]{service},
                new RpcHandler(service));
    }

    
    static class RpcHandler implements InvocationHandler {
        Logger logger = LoggerFactory.getLogger(RpcHandler.class);
        private Class service;

        public RpcHandler(Class service) {
            this.service = service;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            
            //Object result = RemoteCallUtility.request(service.getName(), method.getName(), args);
            String name = service.getName();
            String name1 = method.getName();

            Object result = null;
            //logger.info("参数args:{}",args);
            //
            //JSonArray jsonArray = JSON.parseArray(args.toString());
            //logger.info("转换后的jsonArray:{}",jsonArray);
            result = HttpClientUtil.doPost("http://www.baidu.com", null);
            return result;
        }
    }
}
public class RpcInvoker {
    public void invoke(String name) {
        OrderInterface order = SimpleRpcframe.getRemoteProxy(OrderInterface.class);
        order.addOrder(name);
    }
}
  @Test
    void proxyInterface(){
        RpcInvoker rpcInvoker = new RpcInvoker();
        rpcInvoker.invoke("zhongxu");

    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/425154.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号