zoukankan      html  css  js  c++  java
  • JAVA动态代理cglib或jdk

    cglib或jdk动态代理

    Proxy代理,只把tostrng,equal,hashcode交给handler(原对象)去实现,其他的自己实现,所以调用getclass().getName()时返回$proxy0
    java.lang.reflect.Proxy代理的原理,1.生成代理类。2.如果原对象设置了需要代理(如autowire注解),则返回代理对象(即添加了增强方法的代理对象),返回的对象想要强转,只能强转成接口
    Spring AOP的底层就是通过JDK动态代理或CGLib动态代理技术 为目标Bean执行横向织入。
    1.若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。
    2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
    cglib不但可以接受接口,还能接受普通类。

    package platformc.aoptest;
    
    import lombok.Data;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.ArrayList;
    
    /**
     * @author: CHX
     * @date: 2021/3/28 20:42
     */
    @Data
    public class TestFactory implements MethodInterceptor {
        private Object target;
        private MyAdvice advice = new MyAdvice();
    
        public static void main(String[] args) {
            try {
                //通过代理获取对象
                Object bean = new TestFactory().getBean("platformc.aoptest.TestFactory",
                        "java.util.ArrayList");
                System.out.println(bean.getClass().getName());
                System.out.println(((ArrayList<Object>) bean).size());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 通过代理获取对象
         *
         * @param proxyName  代理对象类名
         * @param targetName 被代理对象类名
         * @return
         * @throws ClassNotFoundException
         * @throws IllegalAccessException
         * @throws InstantiationException
         */
        public Object getBean(String proxyName, String targetName) throws ClassNotFoundException,
                IllegalAccessException, InstantiationException {
            //获取代理对象(实际应用中,可更换为判断注解)
            Class<?> aClass = Class.forName(proxyName);
            Object bean = aClass.newInstance();
            if (bean instanceof TestFactory) {
                //如果代理类是我们自定义的代理类,则开始进行方法增强。
                target = Class.forName(targetName).newInstance();
                //设置被代理对象
                ((TestFactory) bean).setTarget(target);
                return ((TestFactory) bean).getProxy();
            }
            return bean;
        }
    
        /**
         * 分为cglib代理或jdk代理。
         *
         * @return
         */
        public Object getProxy() {
            Object o;
            //分为cglib代理和jdk代理,本身是接口则用jdk,否则用cglib
            if (target.getClass().isInterface()) {
                o = Proxy.newProxyInstance(target.getClass().getClassLoader(),
                        //注意此处,传入是实现的接口。
                        target.getClass().getInterfaces(),
                        (proxy, method, args) -> {
                            advice.befor(method);
                            Object invoke = method.invoke(target, args);
                            advice.after(method);
                            return invoke;
                        });
            } else {
                //创建一个动态类对象,即增强类对象
                Enhancer enhancer = new Enhancer();
                //确定需要增强的类,设置为父类
                enhancer.setSuperclass(target.getClass());
                //确定代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
                enhancer.setCallback(this);
                //返回创建的代理对象
                o = enhancer.create();
            }
            return o;
        }
    
        /**
         * @param o           代理对象本身
         * @param method      被代理对象方法
         * @param objects     被代理对象入参
         * @param methodProxy 可执行代理方法或被代理对象的方法
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            advice.befor(method);
            Object invoke = methodProxy.invokeSuper(o, objects);
            advice.after(method);
            return invoke;
        }
    }

    执行结果

  • 相关阅读:
    每天玩转3分钟 MyBatis-Plus
    每天玩转3分钟 MyBatis-Plus
    每天玩转3分钟 MyBatis-Plus
    git仓库管理
    【SpringCloud之pigx框架学习之路 】2.部署环境
    【SpringCloud之pigx框架学习之路 】1.基础环境安装
    Ubuntu 14.04 安装mysql
    Netflix是什么,与Spring Cloud有什么关系
    现学现用-我的第三个小小小私活
    申请微信小游戏账号
  • 原文地址:https://www.cnblogs.com/chxwkx/p/14590283.html
Copyright © 2011-2022 走看看