zoukankan      html  css  js  c++  java
  • 动态代理


    spring中的AOP就是利用JDK的动态代理来生成对象的,该对象可以作为目标对象使用
    可是sping 中的AOP代理可以有JDK动态代理,也有CGLIB代理。

    JDK 动态代理

    1. 首先创建UserDao,编写两个方法-添加和删除
    package com.java.jdk;
    
    /**
     * Created by IntelliJ IDEA.
     *
     * @version : 1.0
     * @auther : Firewine
     * @mail : 1451661318@qq.com
     * @Program Name: <br>
     * @Create : 2018-12-05-19:12
     * @Description :  <br/>
     */
    public interface UserDao {
        public void addUser();
        public void deleteUser();
    }
    
    1. 实现UserDao 的两个方法
    package com.java.jdk;
    
    /**
     * Created by IntelliJ IDEA.
     *
     * @version : 1.0
     * @auther : Firewine
     * @mail : 1451661318@qq.com
     * @Program Name: <br>
     * @Create : 2018-12-05-19:13
     * @Description :  <br/>
     */
    public class UserDaoImpl implements UserDao{
        //是以这个类作为目标类,进行增强处理
        @Override
        public void addUser() {
            System.out.println("添加用户");
        }
    
        @Override
        public void deleteUser() {
    
            System.out.println("删除用户");
        }
    }
    
    1. 模拟切面,加个两个权限和日志方法
    package com.java.aspect;
    
    /**
     * Created by IntelliJ IDEA.
     *
     * @version : 1.0
     * @auther : Firewine
     * @mail : 1451661318@qq.com
     * @Program Name: <br>
     * @Create : 2018-12-05-19:15
     * @Description :  <br/>
     */
    public class MyAspect {
    
        //下面两个方法模拟切面
        /**
         * 模拟权限检查方法
         */
        public void check_Permissions(){
            System.out.println("权限检查");
        }
        /**
         * 模拟日志方法
         */
        public void log(){
            System.out.println("记录日志");
        }
    }
    
    1. 实现JDK代理类,需要实现InvocationHandle
    package com.java.proxy;
    import com.java.aspect.MyAspect;
    import com.java.jdk.UserDao;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * Created by IntelliJ IDEA.
     *
     * @version : 1.0
     * @auther : Firewine
     * @mail : 1451661318@qq.com
     * @Program Name: <br>
     * @Create : 2018-12-05-19:17
     * @Description :  <br/>
     */
    public class JdkProxy implements InvocationHandler {
    
        //声明目标类接口
        private UserDao userDao;
    
        //创建代理方法
        public Object createProxy(UserDao userDao){
            this.userDao = userDao;
            //1. 类加载器
            ClassLoader classLoader = JdkProxy.class.getClassLoader();
            //2. 被代理对象实现的所有接口
            Class[] classes = userDao.getClass().getInterfaces();
            //3. 使用代理类,进行增强,返回的是代理后的对象
            return Proxy.newProxyInstance(classLoader,classes,this::invoke);
        }
        /**
         * 所有的动态代理类的方法调用,都会交由invoke方法去处理
         * @param proxy  就是被代理后的对象
         * @param method 是要执行的方法(反射)
         * @param args
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            /**
             * 第一个参数 : 当前类的类加载器
             * 第二个参数 : 是被代理对象实现的所有的接口
             * 第三个参数 : 代表代理类JdkProxy的本身
             */
            //声明切面
            MyAspect myAspect  = new MyAspect();
            //前增强
            myAspect.check_Permissions();
            //在目标类上调用方法,传入参数
            Object obj = method.invoke(userDao,args);
            //后增强
            myAspect.log();
            return obj;
        }
    }
    
    1. 最后一个编写测试类
    package com.java.test;
    import com.java.jdk.UserDao;
    import com.java.jdk.UserDaoImpl;
    import com.java.proxy.JdkProxy;
    
    /**
     * Created by IntelliJ IDEA.
     *
     * @version : 1.0
     * @auther : Firewine
     * @mail : 1451661318@qq.com
     * @Program Name: <br>
     * @Create : 2018-12-05-19:25
     * @Description :  <br/>
     */
    public class JdkTest {
    
        public static void main(String[] args) {
            //创建代理对象
            JdkProxy jdkProxy = new JdkProxy()
            //创建目标对象
            UserDao userDao = new UserDaoImpl();
            //从代理对象获取增强后的目标对象
            UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
            userDao1.addUser();
            userDao1.deleteUser();
        }
    }
    
    1. 结果显示
      在这里插入图片描述

    CGLIB代理

    CGLIB 是一个高性能开源的代码生成包,它采用非常底层的字节码结束,对指定的目标类生成一个子类,并对子类进行增强。
    这个也已经被集成到spring的核心包中了

    1. 实现一个目标类
    package com.cglib.jdk;
    
    /**
     * Created by IntelliJ IDEA.
     *
     * @version : 1.0
     * @auther : Firewine
     * @mail : 1451661318@qq.com
     * @Program Name: <br>
     * @Create : 2018-12-05-19:30
     * @Description :  <br/>
     */
    public class UserDao {
        public void addUser() {
            System.out.println("添加用户");
        }
        public void deleteUser() {
            System.out.println("删除用户");
        }
    }
    
    1. 创建代理类,需要实现MethodInterceptor接口,并实现接口的intercept方法
    package com.cglib.proxy;
    import com.java.aspect.MyAspect;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    /**
     * Created by IntelliJ IDEA.
     *
     * @version : 1.0
     * @auther : Firewine
     * @mail : 1451661318@qq.com
     * @Program Name: <br>
     * @Create : 2018-12-05-19:36
     * @Description :  <br/>
     */
    public class CglibProxy implements MethodInterceptor {
    
        public Object CreateProxy(Object object){
            //创建一个动态类对象
            Enhancer enhancer = new Enhancer();
            //确定需要增强的类,设置其父类
            enhancer.setSuperclass(object.getClass());
            //添加回调函数
            enhancer.setCallback( this);
            //返回创建的代理类
            return enhancer.create();
        }
    
        /**
         * proxy CGLIB 根据指定父类生成的代理对象
         * method 拦截的方法
         * args 拦截方法的参数数组
         * methodProxy 方法的代理对象,用于执行父类的方法
         * @param
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            //创建切面类对象
            MyAspect myAspect = new MyAspect();
            myAspect.check_Permissions();
            Object object = methodProxy.invokeSuper(methodProxy,objects);
            myAspect.log();
            return object;
        }
    }
    
    
    1. 创建测试类
    package com.cglib.test;
    
    import com.cglib.jdk.UserDao;
    import com.cglib.proxy.CglibProxy;
    
    /**
     * Created by IntelliJ IDEA.
     *
     * @version : 1.0
     * @auther : Firewine
     * @mail : 1451661318@qq.com
     * @Program Name: <br>
     * @Create : 2018-12-05-19:49
     * @Description :  <br/>
     */
    public class CglibTest {
        public static void main(String[] args) {
            CglibProxy cglibProxy = new CglibProxy();
            UserDao userDao = new UserDao();
            UserDao userDao1 = (UserDao) cglibProxy.CreateProxy(userDao);
            userDao1.addUser();
            userDao1.deleteUser();
        }
    }
    
    1. Enhancer 是CGLIB的核心类,然后调用该类的setSuperclass方法来确定目标对象,然后setCallback方法添加回调函数,
    2. 而且这两个代理的不同之处,就是JDK需要实现接口的但是只需要jdk。而CGLIB是不需要接口的,但是需要导入Spring的核心包。
  • 相关阅读:
    TypeScript02 方法特性【参数种类、参数个数】、generate方法、析构表达式、箭头表达式、循环
    TypeScript01 编译环境的搭建、字符串特性、类型特性
    Angular04 组件动态地从外部接收值、在组件中使用组件
    Angular03 将数据添加到组件中
    Angular02 通过angular-cli来搭建web前端项目
    Angular01 利用grunt搭建自动web前端开发环境、利用angular-cli搭建web前端项目
    IDEA01 创建java项目、创建web项目
    Struts2框架07 Struts2 + Spring + Mybatis 整合
    素数应用
    二重指针实现排序
  • 原文地址:https://www.cnblogs.com/YJBlog/p/10092213.html
Copyright © 2011-2022 走看看