精华内容
参与话题
问答
  • Cglib代理

    2019-06-23 12:47:18
    Cglib代理 Cglib代理适用场景 注意事项 Cglib代理 子类代理,在内存中构建一个子类对象从而实现对目标对象的扩展。 Cglib代理适用场景 有一个目标对象,但是没有接口 import org.springframework.cglib....

    目录

    Cglib代理

    Cglib代理适用场景

    注意事项


    Cglib代理

    子类代理,在内存中构建一个子类对象从而实现对目标对象的扩展。

    Cglib代理适用场景

    有一个目标对象,但是没有接口

    import org.springframework.cglib.proxy.Enhancer;
    //代理工厂提供获取代理的方法
    
    public class CglibProxyFactory {
        public static <T> T getProxyInstance(T t) {
            //使用Cglib生成子类代理步骤
            Enhancer enhancer = new Enhancer();
            //指定生成哪个类的代理
            enhancer.setSuperclass(t.getClass());
            //设置回调(就是想当于设置调用目标对象方法时会进入MyMethodInterceptor的intercept方法)
            enhancer.setCallback(new MyMethodInterceptor());
            //创建子类代理对象
            return (T) enhancer.create();
        }
    }
    
    //新建增强类实现 MethodInterceptor
    public class MyMethodInterceptor implements MethodInterceptor {
        /**
         *前三个参数和InvocationHandler里面的invoke方法参数一样
         * @param o:生成的Cglib代理对象
         * @param method:被拦截的方法
         * @param objects:被拦截的方法的参数
         * @param methodProxy:表示可以触发父类的方法的方法代理对象
         * @return
         * @throws Throwable
         */
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("开始事务---》");
            //是Cglib代理
            System.out.println(o.getClass());
            //父类是目标对象,即Cglib的代理默认都继承自目标对象,是目标对象的子类
            System.out.println(o.getClass().getSuperclass());
            //指调用o的父类的方法,o的父类即是代理对象的父类,即被代理的对象,即目标对象。
            //调用被代理对象的方法
            Object obj = methodProxy.invokeSuper(o, objects);
            System.out.println("提交事务---》");
            return obj;
        }
    }
    

    测试:

    public class TestCglib {
        public static void main(String[] args) {
            UserService userService = new UserService();
            UserService proxyInstance = CglibProxyFactory.getProxyInstance(userService);
            proxyInstance.saveUser();
        }
    }
    

    运行结果:

    注意事项

    1. 有final修饰的类不可以被代理(因为不能有子类)
    2. final或static修饰的方法不可以被拦截

    有final修饰的类

    public final class UserService {
        public void saveUser() {
            System.out.println("保存数据---》" + new User());
        }
    }
    

    运行上面测试代码,报如下异常

    有final或static修饰的方法:

    public class UserService {
        public final void saveUser() {
            System.out.println("保存数据---》" + new User());
        }
    }
    public class UserService {
        public static void saveUser() {
            System.out.println("保存数据---》" + new User());
        }
    }

     

    运行上面测试代码,结果并没有被拦截:

    展开全文
  • CGLIB代理

    2020-08-17 14:45:17
    CGLIB和JDK动态代理一样都是动态代理,但是CGLIB代理没有接口可以进行代理 CGLIB代理没有接口的类,在JVM动态的为这个代理创建一个子类,子类重写父类方法,并且调用父类方法,在父类方法执行之前,之后,异常,最终...

    CGLIB(Code Generation Library)是一个开源项目

    CGLIB和JDK动态代理一样都是动态代理,但是CGLIB代理没有接口可以进行代理

    CGLIB代理没有接口的类,在JVM动态的为这个代理创建一个子类,子类重写父类方法,并且调用父类方法,在父类方法执行之前,之后,异常,最终做增强

    Spring默认已经集成CGLIB代理,直接可以使用即可,不用拷贝任何jar包

    在这里插入图片描述

    案例

    UserServiceImpl

    package cn.zj.spring.service.impl;
    
    import cn.zj.spring.pojo.User;
    import cn.zj.spring.service.UserService;
    
    public class UserServiceImpl {
    	
    	public void insert(User user) {
    		System.out.println("执行dao的层 insert方法");
    	}
    	
    	public final void updateByPrimaryKey(User user) {
    		System.out.println("执行dao的层 update方法");
    	}
    	
    }
    
    

    TransactionManagerHandler

    package cn.zj.spring.utils;
    /*
     * 此类模拟事务管理器(专门处理事务的类)
     * 
     * 提供,开启,提交,回滚,关闭事务相关操作的方法
     * 
     * 
     */
    public class TransactionManagerHandler {
    
    	public void begin() {
    		System.out.println("开启事务");
    	}
    	public void commit() {
    		System.out.println("提交事务");
    	}
    	public void rollback() {
    		System.out.println("回滚事务");
    	}
    	public void close() {
    		System.out.println("释放资源");
    	}
    }
    
    

    CGLIBProxyHandler

    package cn.zj.spring.utils;
    
    import java.lang.reflect.Method;
    
    import org.springframework.cglib.proxy.Enhancer;
    
    import cn.zj.spring.service.impl.UserServiceImpl;
    
    /*
     * 
     * 	此类是创建代理对象的类,最有一个终返回代理对象方法
     * 
     * ------------------------
     * 
     *    创建代理对象要注入相关条件(对象)
     * 1,被代理的对象
     * 		当前场景 UserService接口的实现类 UserServiceImpl 的对象
     * 2,要增强的功能
     * 		当前场景就是  模拟的事务管理器 TransactionManagerHandler
     * 
     * 	最终在创建代理对象的过程,将模拟事务管理器功能,增强到 被代理对象的每一个方法上面 (insert,update,delete...)
     * 
     * 3,提供一个返回代理对象的方法
     * 	在方法内部完成创建代理对象的过程
     * 
     * 
     * 
     */
    public class CGLIBProxyHandler {
    	
    	/*
    	 * 	1, 被代理的对象,理论上应该是 UserService接口的实现类 UserServiceImpl 的对象
    	 *  	实际一般使用超级父类  Object
    	 */
    	private Object target;
    	
    	/*
    	 * 2 ,模拟事务管理器
    	 * 		要在代理对象里面增强的功能
    	 */
    	private TransactionManagerHandler txManager;
    	
    	
    	//3,提供一个返回代理对象的方法
    	//在方法内部完成创建代理对象的过程
    	public UserServiceImpl getProxyObject() {
    		/*
    		 * 
    		 * 	使用CGLIB创建代理对象
    		 * 
    		 * 
    		 */
    		
    		//1.创建Enhancer 对象
    		Enhancer enhancer = new Enhancer();
    		
    		//2.设置类加载器
    		enhancer.setClassLoader(Thread.currentThread().getContextClassLoader());
    		
    		//3.设置被代理类型的字节码实例
    		enhancer.setSuperclass(target.getClass());
    		
    		//4.设置执行处理器
    		enhancer.setCallback(new org.springframework.cglib.proxy.InvocationHandler() {
    			
    			/**
    			 * 此方法就是Java的Proxy创建代理对象以后,开发者在此方法中为创建代理对象的方法做增强的地方
    			 *  如 :方法执行之前,之后,异常,最终 相关事务增强
    			 *  
    			 * @param proxy 创建出来的代理对象
    			 * @param method 被代理对象的方法
    			 * @param args 被代理对象方法的参数
    			 * @return  被代理对象方法执行的结果
    			 * @throws Throwable
    			 */
    			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    				/*
    				 * 增强的逻辑
    				 * 使用反射执行被代理对象的方法,在方法之前,之后, 异常,最终做模拟事务管理器的事务增强
    				 * 
    				 */
    				
    				
    				
    				Object result = null;
    				try {
    
    					//开始事务
    					txManager.begin();
    					//使用反射执行被代理对象
    					result = method.invoke(target, args);
    					
    					//提交事务
    					txManager.commit();
    					
    				} catch (Exception e) {
    					e.printStackTrace();
    					//回滚事务
    					txManager.rollback();
    				}finally {
    					txManager.close();
    				}
    				
    				return result;
    			}
    		});
    		
    		//5.使用Enhancer对象创建代理对象
    		Object proxyObject = enhancer.create();
    		
    		
    		
    		
    		return (UserServiceImpl) proxyObject;
    	}
    	
    	
    	public void setTarget(Object target) {
    		this.target = target;
    	}
    	public void setTxManager(TransactionManagerHandler txManager) {
    		this.txManager = txManager;
    	}
    }
    
    

    测试代码

    package cn.zj.spring.test;
    
    import static org.junit.Assert.*;
    
    import java.util.List;
    
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import cn.zj.spring.pojo.User;
    import cn.zj.spring.service.UserService;
    import cn.zj.spring.service.impl.UserServiceImpl;
    import cn.zj.spring.utils.CGLIBProxyHandler;
    
    import org.junit.runner.RunWith;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class UserServiceTest {
    
    	/*
    	 * 此对象并不是代理对象,而是返回代理对象的对象
    	 * 
    	 * 里面的 getProxyObject 方法返回才是代理对象
    	 * 
    	 */
    	@Autowired
    	private CGLIBProxyHandler proxyHandler;
    
    	@Test
    	public void testInsert() {
    
    		User user = new User(null, "钢铁侠", "gtx@qq.com");
    
    		// 获取代理对象
    		UserServiceImpl userService = proxyHandler.getProxyObject();
    		// cn.zj.spring.service.impl.UserServiceImpl$$EnhancerByCGLIB$$8f3abe2c
    		System.out.println(userService.getClass().getName());
    
    		userService.insert(user);
    
    	}
    
    	@Test
    	public void testUpdateByPrimaryKey() {
    		User user = new User(2, "蜘蛛侠", "zhizhuxia@qq.com");
    
    		// 获取代理对象
    		UserServiceImpl userService = proxyHandler.getProxyObject();
    
    		userService.updateByPrimaryKey(user);
    
    	}
    
    	@Test
    	public void testName() throws Exception {
    		// 获取代理对象
    		UserServiceImpl userService = proxyHandler.getProxyObject();
    		userService.toString();
    //		userService.getClass();
    	}
    
    }
    
    

    测试结果

    在这里插入图片描述

    CGLIB代理总结

    1,CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。
    2,要求类不能是final的,要代理的方法要是非final、非static、非private的。
    3,动态代理的最小单位是类(所有类中的方法都会被处理);

    动态代理模式的缺陷是什么

    动态代理模式的缺陷是:
    1. 必须需要实现类必须要有一个接口 -JDK动态代理
    2. 无法通过规则制定拦截的方法

    如何解决这个问题?

    答:Spring提供了AOP的实现。

    展开全文
  • cglib代理

    2019-07-12 18:48:31
    cglib代理 ​ 在此之前,我们学习了JDK动态代理,而JDK动态代理有一定的局限性,因为使用JDK动态代理时,被代理类必须实现接口,然后动态代理生成的代理类同时实现该接口实现代理模式,但在特定情况下没办法让被代理...

    cglib代理

    ​ 在此之前,我们学习了JDK动态代理,而JDK动态代理有一定的局限性,因为使用JDK动态代理时,被代理类必须实现接口,然后动态代理生成的代理类同时实现该接口实现代理模式,但在特定情况下没办法让被代理类实现接口,那么此时我们就需要使用cglib代理。

    代理模式的三要素

    • 两个成员:被代理对象、执行者(类似于Spring中切面的概念)
    • 使用场景:当某件事情不方便自己做,但是必须要做时使用代理模式。
    • 代理对象持有被代理对象的引用。

    ​ 在第一点中,执行者指的是代理对象的执行模板,例如在JDK动态代理中,实现InvocationHandler接口的类就是代理类中方法的执行模板。而在cglib代理中执行模板需要实现MethodInterceptor

    使用cglib需要做的准备

    JDK动态代理由于是JDK自带的,所以我们不需要在项目中引入第三方jar,但是cglib需要引入两个jar包:
    在这里插入图片描述

    cglib代理具体实例

    创建被代理类

    package _6代理模式.CGlib代理;
    
    public class UserService  {
    
        public void addUser(){
            System.out.println("添加用户");
        }
    
        public void deleteUser() {
            System.out.println("删除用户");
        }
    
    }
    
    

    创建执行者

    package _6代理模式.CGlib代理;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * 执行者
     */
    public class Executent implements MethodInterceptor {
        /**
         *
         * @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 {
            System.out.println("开启事务");
            Object result= null;
            try {
                result = methodProxy.invokeSuper(o,objects);
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                System.out.println("回滚事务");
            }
            System.out.println("提交事务");
            return result;
        }
    }
    

    通过cglib生成代理对象

    public class TestCglib {
        public static void main(String[] args) {
           	Enhancer enhancer = new Enhancer();
            //设置父类
            enhancer.setSuperclass(UserService.class);
            //设置执行者
            enhancer.setCallback(new Executent());
            //创建代理对象
            UserService userService = (UserService) enhancer.create();
            userService.addUser();
        }
    }
    

    执行结果:

    [外链图片转存失败(img-dLKjZne6-1562928349224)(…/images/27.png)]# cglib代理

    ​ 在此之前,我们学习了JDK动态代理,而JDK动态代理有一定的局限性,因为使用JDK动态代理时,被代理类必须实现接口,然后动态代理生成的代理类同时实现该接口实现代理模式,但在特定情况下没办法让被代理类实现接口,那么此时我们就需要使用cglib代理。

    代理模式的三要素

    • 两个成员:被代理对象、执行者(类似于Spring中切面的概念)
    • 使用场景:当某件事情不方便自己做,但是必须要做时使用代理模式。
    • 代理对象持有被代理对象的引用。

    ​ 在第一点中,执行者指的是代理对象的执行模板,例如在JDK动态代理中,实现InvocationHandler接口的类就是代理类中方法的执行模板。而在cglib代理中执行模板需要实现MethodInterceptor

    使用cglib需要做的准备

    JDK动态代理由于是JDK自带的,所以我们不需要在项目中引入第三方jar,但是cglib需要引入两个jar包:

    [外链图片转存失败(img-fEj9OQOA-1562928350449)(…/images/26.png)]

    cglib代理具体实例

    创建被代理类

    package _6代理模式.CGlib代理;
    
    public class UserService  {
    
        public void addUser(){
            System.out.println("添加用户");
        }
    
        public void deleteUser() {
            System.out.println("删除用户");
        }
    
    }
    
    

    创建执行者

    package _6代理模式.CGlib代理;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * 执行者
     */
    public class Executent implements MethodInterceptor {
        /**
         *
         * @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 {
            System.out.println("开启事务");
            Object result= null;
            try {
                result = methodProxy.invokeSuper(o,objects);
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                System.out.println("回滚事务");
            }
            System.out.println("提交事务");
            return result;
        }
    }
    

    通过cglib生成代理对象

    public class TestCglib {
        public static void main(String[] args) {
           	Enhancer enhancer = new Enhancer();
            //设置父类
            enhancer.setSuperclass(UserService.class);
            //设置执行者
            enhancer.setCallback(new Executent());
            //创建代理对象
            UserService userService = (UserService) enhancer.create();
            userService.addUser();
        }
    }
    

    执行结果:

    展开全文
  • CGLIb代理

    2019-04-27 15:11:46
    CGLIb代理 JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用...

    CGLIb代理

    JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

    简单的实现举例:

    public class CGLibProxy implements MethodInterceptor {
     private Object targetObject;
     public Object CreateProxy(Object obj) {
      this.targetObject = obj;
      Enhancer enhancer = new Enhancer();// 增强类
      enhancer.setSuperclass(targetObject.getClass());// 设置父类
      enhancer.setCallback(this);//
      return enhancer.create(new Class[] { String.class, String.class },
        new Object[] { null, null });// ok
      // return enhancer.create(targetObject.getClass(), this);// ok,需要无参构造
     }
     @Override
     public Object intercept(Object arg0, Method method, Object[] args,
       MethodProxy arg3) throws Throwable {
      // TODO Auto-generated method stub
      System.out.println("\n前置条件及准备工作");
      MyLog mylog = method.getDeclaredAnnotation(MyLog.class);
      Object obj = null;
      if (mylog != null) {
       obj = method.invoke(targetObject, args);
       Student st = (Student) targetObject;
       System.out.println("学生名:" + st.getName() + ",地址:" + st.getAddress()
         + "---被调用了" + method.getName() + "方法");
      } else {
       System.out.println(method.getName() + "方法,没注解");
      }
      System.out.println("后置条件及准备工作\n");
      return obj;
     }
    }
    

    注:之前再写的时候发现实体类,必须先生成无参构造,否则报错,超类没有空构造函数,但是没有给出参数,使用上述方法就避免了,他通过实例的有参构造,获取对象.
    报错如下:

    Exception in thread "main" java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
    
    展开全文
  • CGLib代理

    2017-02-27 19:15:00
    Spring框架,如果类实现了接口,就使用JDK的动态代理生成代理对象,如果这个类没有实现任何接口,使用CGLIB生成代理对象.JDk强制要求必须有接口来实现动态代理,然而CGLib代理不需要必须有接口才能实现代理,而是通过一...
  • cglib 代理

    2016-05-09 11:25:51
    使用cglib 代理需要导入两个包(asm-3.3.1.jar、cglib-2.2.2.jar)导包的时候你要观察你导入这两个包是否兼容。 1飞机类: package com.jxufe.cglibproxy; /** * 飞机类 * @author jack * @version 创建时间:...
  • cglib代理jar包

    2018-10-18 10:17:05
    cglib代理jar包
  • Cglib代理解密

    千次阅读 2020-09-29 23:32:09
    Cglib代理原理解密 cglib与动态代理功能类似,都是为了做方法拦截的,从而增强方法功能,本文讲解cglib的原理 我有一个CglibDemo类,也就是main方法的测试类, 他有一个属性name和他的get set方法 import ...
  • Cglib代理模式

    2020-09-13 11:46:02
    Cglib代理模式 Cglib代理模式,pom.xml <dependencies> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version>...
  • CGLIB代理模式

    2019-09-04 22:40:09
    1、那么jdk代理模式和CGLIb代理模式有什么区别呢? jdk缺点:jdk动态代理要求被代理类必须实现接口,而代理类如果没有实现接口则会报错,而报错是因为找不到被代理类的父类! cglib优点:cglib是通过字节码的方式,...
  • Java JDK代理与CGLIB代理

    2019-07-17 20:29:42
    Java JDK代理与CGLIB代理区别 1、JDK代理与CGLIB代理程序结构
  • JDK代理和CGLIB代理

    2019-09-15 22:01:36
    java可以分为JDK动态代理和CGLIB代理。JDK动态代理只能对实现了接口的类生成代理,而不能针对类。CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成...
  • Spring CGLIB代理

    2020-04-06 22:13:44
    如果想代理没有实现接口的类,那么可以使用CGLIB代理。CGLIB (Code Generation Library)是一个高性能开源的代码生成包,它采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强。 与JDK实现同样...

空空如也

1 2 3 4 5 ... 20
收藏数 11,663
精华内容 4,665
关键字:

cglib代理