zoukankan      html  css  js  c++  java
  • 23种设计模式——代理模式

    相信大家都知道,有23种代理模式,其中用得比较多的或者是面试中估计问的最多的就是动态代理,但是我们知道,动态代理,静态代理都只是23种设计模式中的代理模式。好了,话不多说,直接上干货。

    代理模式

       1、动态代理

           先创建接口:

           

    /**
     * 功能描述
     *
     * @author yaoqihui
     * @version 2021/7/4
     * @see [相关类/方法]
     * @since [malan-rabbitmq]
     */
    public interface UserService {
        void saveUser();
    }

          写一个类,实现接口:

    import com.sailmalan.malan.service.UserService;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * 功能描述
     *
     * @author yaoqihui
     * @version 2021/7/4
     * @see [相关类/方法]
     * @since [malan-rabbitmq]
     */
    @Slf4j
    public class UserServiceImpl implements UserService {
        @Override
        public void saveUser() {
            log.info("动态代理调用");
        }
    }

     创建代理类(可以重复利用)


    import lombok.extern.slf4j.Slf4j;

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

    /**
    * 动态代理类
    *
    * @author yaoqihui
    * @version 2021/7/4
    * @see [相关类/方法]
    * @since [malan-rabbitmq]
    */
    @Slf4j
    public class InvocationHandlerImpl implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //method.invoke()方法,真正动态代理的地方,利用的是java的反射,大伙也可以看到包:java.lang.reflect.Method
    return method.invoke(target, args);
    }
    }

    动态代理测试类:

    import com.sailmalan.malan.service.UserService;
    import com.sailmalan.malan.service.impl.UserServiceImpl;
    
    import java.lang.reflect.Proxy;
    
    /**
     * 功能描述:生成UserService,供调用---》类似于我们使用springBoot的注解,得到一个userService接口
    @Autowired
    private UserService userService; * *
    @author yaoqihui * @version 2021/7/4 * @see [相关类/方法] * @since [malan-rabbitmq] */
    public class TestInvocationHandler {
    public static void main(String[] args) {
    /************************类似于达到效果的注解:
    * @Autowired
    * private UserService userService;
    * 开始代码**************************/
    UserService userService = new UserServiceImpl();
    InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(userService);
    ClassLoader loader = userService.getClass().getClassLoader();
    Class<?>[] interfaces = userService.getClass().getInterfaces();
    UserService newProxyInstance = (UserService) Proxy.newProxyInstance(loader, interfaces, invocationHandler);
    /************************结束代码**************************/
    newProxyInstance.saveUser();
    }
    }

    2、CGLIB静态代理

    • CGLIB动态代理和jdk代理一样,使用反射完成代理,不同的是他可以直接代理类(jdk动态代理不行,他必须目标业务类必须实现接口),CGLIB动态代理底层使用字节码技术,CGLIB动态代理不能对 final类进行继承。(CGLIB动态代理需要导入jar包)
        //接口
        public interface UserDao {
            void save();
        }
    //接口实现类
    public class UserDaoImpl implements UserDao {
        public void save() {
            System.out.println("保存数据方法");
        }
    }

    代理类:

    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    
    //代理主要类
    public class CglibProxy implements MethodInterceptor {
        private Object targetObject;
        // 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理
        public Object getInstance(Object target) {
            // 设置需要创建子类的类
            this.targetObject = target;
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        //代理实际方法
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("开启事物");
            Object result = proxy.invoke(targetObject, args);
            System.out.println("关闭事物");
            // 返回代理对象
            return result;
        }
    }

    测试:

    //测试CGLIB动态代理
    public class Test {
        public static void main(String[] args) {
            CglibProxy cglibProxy = new CglibProxy();
            UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDaoImpl());
            userDao.save();
        }
    }

    2、静态代理代码演示

     创建UserDao类:

        //接口类
        public class UserDao{
            public void save() {
                System.out.println("保存数据方法");
            }
        }

    添加代理类

    //代理类
    public class UserDaoProxy extends UserDao {
        private UserDao userDao;
       //此处是构造器注入
        public UserDaoProxy(UserDao userDao) {
            this.userDao = userDao;
        }
    
        public void save() {
            System.out.println("开启事物...");
            userDao.save();
            System.out.println("关闭事物...");
        }
    
    }

    下面测试静态代理的类:

    //添加完静态代理的测试类
    public class Test{
        public static void main(String[] args) {
            UserDao userDao = new UserDao();
            UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);
            userDaoProxy.save();
        }
    }

  • 相关阅读:
    常用正则、正则表达式
    移动端虚拟手机键盘
    如何隐藏滚动条还能实现滚动的功能
    醉盏的第一篇博客-关于title的换行处理
    Mybatis-Generator自动生成Dao、Model、Mapping等相关映射文件(懒人版)
    java学习笔记----@Override的作用
    web项目生成web.xml的两种方式
    angular分页插件tm.pagination二次触发问题解决歪方案
    Ubuntu Server17.10配置静态IP
    cors 的深入细节
  • 原文地址:https://www.cnblogs.com/qq1141100952com/p/15055342.html
Copyright © 2011-2022 走看看