enhancer_请问enhancer和methodinterceptor在哪个包里 - CSDN
精华内容
参与话题
  • cglib中Enhancer的简单使用

    千次阅读 2015-11-16 20:45:49
    JDK自从1.3版本开始,就引入了动态代理,JDK的动态代理用起来非常简单,但是它有一个限制,就是使用动态代理的对象必须实现一个或多个接口 。如果想代理没有实现接口的类可以使用CGLIB包。  CGLIB是一个强大的高...

     JDK自从1.3版本开始,就引入了动态代理,JDK的动态代理用起来非常简单,但是它有一个限制,就是使用动态代理的对象必须实现一个或多个接口 。如果想代理没有实现接口的类可以使用CGLIB包。
      CGLIB是一个强大的高性能的代码生成包。它被许多AOP的框架(例如Spring AOP)使用,为他们提供方法的interception(拦截)。Hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联。EasyMock通过使用模仿(moke)对象来测试java代码的包。它们都通过使用CGLIB来为那些没有接口的类创建模仿(moke)对象。
      CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉

     

    以下为模拟案例,在使用CGLIB时需引入cglib-nodep-2.1_3.jar包

    简单的使用方法

    Enhancer中有几个常用的方法, setSuperClass和setCallback, 设置好了SuperClass后, 可以使用create制作代理对象了

    Enhancer enhancer = new Enhancer();  
    enhancer.setSuperclass(EnhancerDemo.class);  

    enhancer.setCallback(new MethodInterceptorImpl());  
    EnhancerDemo demo = (EnhancerDemo) enhancer.create(); 

     

     

    实现MethodInterceptor接口

    private static class MethodInterceptorImpl implements MethodInterceptor {  


            
            public Object intercept(Object obj, Method method, Object[] args,  
                    MethodProxy proxy) throws Throwable {  
                System.out.println("Before invoke " + method);  
                Object result = proxy.invokeSuper(obj, args);  
                System.out.println("After invoke" + method);  
                return result;  
            }    
        } 

    intercept方法, Object result = proxy.invokeSuper(obj, args)调用了原来的方法, 在这个调用前后可以添加其他的逻辑, 相当于AspectJ的around

    完整代码如下: 

    import java.lang.reflect.Method;  
    import net.sf.cglib.proxy.Enhancer;  
    import net.sf.cglib.proxy.MethodInterceptor;  
    import net.sf.cglib.proxy.MethodProxy;  

    public class EnhancerDemo {  
        public static void main(String[] args) {  
            Enhancer enhancer = new Enhancer();  
            enhancer.setSuperclass(EnhancerDemo.class);  
            enhancer.setCallback(new MethodInterceptorImpl());  
               
            EnhancerDemo demo = (EnhancerDemo) enhancer.create();  
            demo.test();           
            System.out.println(demo);  
        }  
           
        public void test() {  
            System.out.println("EnhancerDemo test()");  
        }  

       
        private static class MethodInterceptorImpl implements MethodInterceptor {  
            @Override 
            public Object intercept(Object obj, Method method, Object[] args,  
                    MethodProxy proxy) throws Throwable {  
                System.err.println("Before invoke " + method);  
                Object result = proxy.invokeSuper(obj, args);  
                System.err.println("After invoke" + method);  
                return result;  
            }            
        }  

    展开全文
  • Enhancer的简单实践

    2020-07-08 17:10:30
    需求: 对指定类的方法做代理。 可以使用Proxy+InvocationHandler实现,但是如果代理类没有父接口的情况下,如何快速实现?... Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MyHandler

    需求:

    对指定类的方法做代理。

    可以使用Proxy+InvocationHandler实现,但是如果代理类没有父接口的情况下,如何快速实现?

    spring的cglib下提供的Enhancer可以快速实现对某个类的所有实例方法(除final)进行代理。

    public static void main(String[] args) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(MyHandler.class);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
                    System.out.println("before");
                    System.out.println(">>>>>>>" + method.getName());
                    //注意此处调用的invokeSuper
                    Object invoke = methodProxy.invokeSuper(o, objects);
                    System.out.println("after");
                    return invoke;
                }
            });
    
            MyHandler handler = (MyHandler) enhancer.create();
            handler.method();
            handler.finalMethod();//没有代理
            handler.protectMethod();
            MyHandler.staticMethod();//没有代理
        }
    public class MyHandler {
    
        public String method(){
            System.out.println("hello Enhancer");
            return "2";
        }
    
        public final String finalMethod(){
            System.out.println("hello finalMethod");
            return "3";
        }
    
        public static String staticMethod(){
            System.out.println("hello staticMethod");
            return "4";
        }
    
    
        protected String protectMethod(){
            System.out.println("hello protectMethod");
            return "5";
        }
    }

    总的来说比较方便就实现了对方法的代理

    展开全文
  • CGLib之Enhancer

    万次阅读 2016-06-15 01:30:32
    Enhancer允许为非接口类型创建一个Java代理。Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是类他都能正常工作。 来个场景模拟一下AOP package cglib.enhancer; ...

    Enhancer允许为非接口类型创建一个Java代理。Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是类他都能正常工作。

    来个场景模拟一下AOP

    package cglib.enhancer;
    
    public class Hello {
    	public String sayHello(boolean throwException) throws Exception {
    		System.out.println("hello everyone!");
    		if(throwException)
    			throw new Exception("test exception");
    		return "123";
    	}
    }

    ProxyFactory用于创建增强代理实现了方法拦截

    package cglib.enhancer;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class ProxyFactory implements MethodInterceptor {
    	 //要代理的原始对象
        private Object obj;
    	public Object createProxy(Object target) {
    		this.obj = target;
    		Enhancer enhancer = new Enhancer();
    		enhancer.setSuperclass(this.obj.getClass());// 设置代理目标
    		enhancer.setCallback(this);// 设置回调
    		enhancer.setClassLoader(target.getClass().getClassLoader());
    		return enhancer.create();
    	}
    
    	@Override
    	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    		Object result = null;
    		try {
    			// 前置通知
    			before();
    			result = proxy.invokeSuper(obj, args);
    			// 后置通知
    			after();
    		} catch (Exception e) {
    			exception();
    		}finally{
    			beforeReturning();
    		}
    		return result;
    	}
    
    
    	private void before() {
    		System.out.println("before method invoke");
    	}
    	private void after() {
    		System.out.println("after method invoke");
    	}
    	private void exception() {
    		System.out.println("method invoke exception");
    	}
    	private void beforeReturning() {
    		System.out.println("before returning");
    	}
    }
    
    场景类:

    package cglib.enhancer;
    
    public class EnhancerTest {
    	public static void main(String[] args) throws Exception {
    		Hello hello = new Hello();
    		ProxyFactory cglibProxy = new ProxyFactory();
    		Hello proxy = (Hello) cglibProxy.createProxy(hello);
    		String result=proxy.sayHello(true);
    		System.out.println(result);
    	}
    }
    

    运行结果:

    before method invoke
    hello everyone!
    method invoke exception
    before returning
    null
    
    当然把true改为false之后结果变为:

    before method invoke
    hello everyone!
    after method invoke
    before returning
    123
    

    接下来我们了解下Enhancer可以使用的Callback接口。

    package net.sf.cglib.proxy;
    
    /**
     * All callback interfaces used by {@link Enhancer} extend this interface.
     * @see MethodInterceptor
     * @see NoOp
     * @see LazyLoader
     * @see Dispatcher
     * @see InvocationHandler
     * @see FixedValue
     */
    public interface Callback
    {
    }
    Callback接口是一个空接口,没有任何契约方法,它只表示这是一个回调。接下来看它的子接口:


    接口都很简单。

    先来一个基础POJO类:

    public class SampleClass {
      public String test(String input) {
        return "Hello world!";
      }
    }

    FixedValue 

    使用FixedValue可以很容易的替换掉方法的返回值。

    @Test
    public void testFixedValue() throws Exception {
      Enhancer enhancer = new Enhancer();
      enhancer.setSuperclass(SampleClass.class);
      enhancer.setCallback(new FixedValue() {
        @Override
        public Object loadObject() throws Exception {
          return "Hello cglib!";
        }
      });
      SampleClass proxy = (SampleClass) enhancer.create();
      assertEquals("Hello cglib!", proxy.test(null));
    }
    在上面的例子中,enhancer返回一个SampleClass的子类实例,当所有的方法被调用的时候返回匿名FixedValue回调返回的值。当然了如果方法返回的不是String类型例如,hashcode()将抛出一个类型转换异常,因为"Hello cglib!"不能转换为java.lang.Number类型。

    InvocationHandler

    @Test
    public void testInvocationHandler() throws Exception {
      Enhancer enhancer = new Enhancer();
      enhancer.setSuperclass(SampleClass.class);
      enhancer.setCallback(new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
          if(method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) {
            return "Hello cglib!";
          } else {
            throw new RuntimeException("Do not know what to do.");
          }
        }
      });
      SampleClass proxy = (SampleClass) enhancer.create();
      assertEquals("Hello cglib!", proxy.test(null));
      assertNotEquals("Hello cglib!", proxy.toString());
    }
    这个回调允许你去回答调用的方法。但是你要小心使用这个回调,因为这个代理对象的所有的方法调用都会使用InvocationHandler#invoke方法,这样的话可能导致死循环。为了避免这种情况你可以使用MethodInterceptor。

    MethodInterceptor

    @Test
    public void testMethodInterceptor() throws Exception {
      Enhancer enhancer = new Enhancer();
      enhancer.setSuperclass(SampleClass.class);
      enhancer.setCallback(new MethodInterceptor() {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
            throws Throwable {
          if(method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) {
            return "Hello cglib!";
          } else {
            return proxy.invokeSuper(obj, args);
          }
        }
      });
      SampleClass proxy = (SampleClass) enhancer.create();
      assertEquals("Hello cglib!", proxy.test(null));
      assertNotEquals("Hello cglib!", proxy.toString());
      proxy.hashCode(); // Does not throw an exception or result in an endless loop.
    }

    唯一需要注意的就是proxy.invokeSuper和proxy.invoke的区别。invokeSuper是退出当前interceptor的处理,进入下一个callback处理,invoke则会继续回调该方法,如果传递给invoke的obj参数出错容易造成递归调用。

    LazyLoader

    尽管LazyLoader唯一的方法和FixedValue的一模一样,但是他们还是有一个根本上的区别。
    相比于Dispatcher,lazyLoader在第一次获取了loadObject后,会进行缓存,后续的请求调用都会直接调用该缓存的属性。
    这个是有道理的,如果你的对象是昂贵的在其创建,不知道对象什么时候被使用。请注意,一些增强的类的构造函数必须被代理对象和延迟加载的对象。因此,确保还有另一个廉价的(可能保护)构造函数获得或使用一个接口类型的代理。你可以选择提供参数的调用Enhancer#create(Object...)。

    Dispatcher

    DispatcherLazyLoader很想但是每次调用方法的时候不会存储加载的对象。这允许改变一个类的实现但不改变原来的对象。
    再者说一些构造函数必须被代理和生成的对象调用。

    ProxyRefDispatcher

    这个类携带了代理对象的引用,通过它的签名调用。例如这允许委托方法调用代理的另一个方法。要清楚这很容易造成死循环,并且总是导致死循环如果同样的方法被ProxyRefDispatcher#loadObject(Object)调用。

    NoOp

    像名字所说的一样,这个类不做任何操作。相反地,它委托每个方法的调用给被增强类的方法实现。
    展开全文
  • cglib中Enhancer介绍

    2020-03-21 16:43:47
    1、Enhancer是一个类的增强器,可以完成对类的代理,在Spring中经常可以看到他的身影比如@Configuration注解的类就会被Enhancer代理。代理时底层用了个字节码处理ASM,ASM是个很牛的东西关于ASM请看我博客里的另一篇...

    一、本文内容分类

    1、接口功能。

    2、接口运用场景。

    3、使用案例。

    4、注意事项。

    二、接口功能介绍

    1、Enhancer是一个类的增强器,可以完成对类的代理,在Spring中经常可以看到他的身影比如@Configuration注解的类就会被Enhancer代理。代理时底层用了个字节码处理ASM,ASM是个很牛的东西关于ASM请看我博客里的另一篇文章。Enhancer的源码比较多,我这里就简单地贴一些。

    因为Enhancer目的就是为了完成代理,所有我们称之为代理类,被代理的类我们称目标类。
    
    private Class[] interfaces;//存的是代理类实现的所有接口。
    private CallbackFilter filter; 
    private Callback[] callbacks; //回调函数,这个很厉害。
    private Class superclass;//该代理的父类,也就是目标类

    2、上面属性中有个callbacks字段,类型是Callback,回想下我们在开发中用过Callback的哪些子类,大名鼎鼎的MethodInterceptor不知道大家还有没有印象,这个类可以拦截我们的目标方法。想象下这个类多么恐怖,不仅能代理你的类,还能拦截你的方法,Spring Aop就是这样实现的。下面Enhancer类结合MethodInterceptor写个简单的Demo。

    三、接口运用场景

    四、使用案例。

    1、有个目标类A,通过Enhancer来完成代理,往Enhancer里面添加拦截器,拦截A的方法,拦截后再调用目标类的方法。

    2、目标类IndexDao

    public class IndexDao {
        //添加一个查询方法。
    	public void query(){
    		System.out.println("indexDao-query");
    		return ;
    	}
    
    }

    2、拦截器类MyMethodInterceptor

    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class MyMethodInterceptor implements MethodInterceptor {
    	@Override
    	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    		//o表示目标类,method目标类的方法,objects目标类方法需要的形参,methodProxy表示代理类+目标方法。
    		System.out.println("拦截("+method.getName()+")方法");
    		//执行目标类的方法。
    		return methodProxy.invokeSuper(o,objects);
    	}
    }

    3、Enhancer类

    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class AppTest {
        public static void main(String[] args) {
    		// 先创建一个代理对象
    		Enhancer enhancer = new Enhancer();
    		// 要代理的对象的class
    		enhancer.setSuperclass(IndexDao.class);
    		// 设置代理的回调,Callback的实现类
    		enhancer.setCallback(new MyMethodInterceptor());
    		//创建代理对象
    		IndexDao indexDao = (IndexDao) enhancer.create();
    		indexDao.query();
        }
    }

    4、打印结果

    拦截(query)方法
    indexDao-query

    5、结果分析

    在执行query()时,先执行了intercept方法,就好比在执更新操作前申明事务,在执行methodProxy.invokeSuper(o,objects)方法如果报错,我们就可以在这行代码后面添加回滚代码。

    五、注意事项

    1、MethodInterceptor拦截的是该类下手动添加的方法,像一些toString,hasCode这种,如果没有重写是不会拦截的。

    2、enhancer.create()里面的知识点还是挺多的,感兴趣的可以深入理解下。

     

    有问题的地方也麻烦大家在下面留言,我在进一步完善下哈。

    展开全文
  • Cglib之Enhancer创建动态代理

    万次阅读 2018-09-22 18:46:31
    Enhancer是一个非常重要的类,它允许为非接口类型创建一个JAVA代理,Enhancer动态的创建给定类的子类并且拦截代理类的所有的方法,和JDK动态代理不一样的是不管是接口还是类它都能正常工作。 net.sf.cglib.pr...
  • Enhancer是啥

    2019-12-08 19:24:48
    Enhancer是cglib中使用频率很高的一个类,它是一个字节码增强器,可以用来为无接口的类创建代理。它的功能与java自带的Proxy类挺相似的。它会根据某个给定的类创建子类,并且所有非final的方法都带有回调钩子。对于...
  • CGLIB enhancer增强类实现

    千次阅读 2019-06-14 16:16:56
    JDK动态代理,Proxy,是必须实现接口才能进行代理,如果一个类没实现接口,就不能使用Proxy动态代理。那么我们可以使用CGLIB(Code Generation Library)动态代理,来实现增强。 使用CGLIB的前提: ...
  • 出现异常:java.lang.NoClassDefFoundError: Could not initialize class net.sf.cglib.proxy.Enhancer, 解决方法:  方案1:删除asm-2.2.3.jar;  方案2:删除 cglib-2.1.3.jar;  保留 cglib-node...
  • 使用Enhance字节码增强创建动态...Enhancre enhancer = new Enhancer(); enhancer.setSuperclass(目标对象的类对象); enhancer.setCallback(new MethodInterceptor(){ @Override public Object intercept(Objec...
  • https://enhancer.io/
  • 经典的AOP一般通过Spring框架,实际上用CGLib更简便、更可控。 动态代理的实现非常优雅。   实体类: ...public class SampleClass { ... public String MyFunction1(String input) { ... System.out.println(...
  • cglib jar包中Enhancer的简单使用

    千次阅读 2012-08-02 10:42:14
    Enhancer中有几个常用的方法, setSuperClass和setCallback, 设置好了SuperClass后, 可以使用create创建代理对象 Enhancer enhancer = new Enhancer();  enhancer.setSuperclass(EnhancerTest.class); enhancer....
  • 区别Proxy是基于接口的方式进行代理,Enhancer是基于继承的方式代理。 proxy是java.lang.reflect.* enhancer是net.sf.cglib.*测试代码:package main;import net.sf.cglib.proxy.Enhancer; import ...
  • tesseract简介: 光学识别 只能识别简单的验证码 识别效率低下,很少使用 转化为灰度图片 使用: 安装tesseract 然后要设置环境变量 Tesseract 3e0p.png lala 识别3e0p图片,然后新建一个lala.txt保存识别的...
  • 绝大多数情况下,您只需编写 SQL,无需编写代码,即可快速完成各类系统的开发,并且获得可直接部署在您私有环境的应用程序。极大降低您的开发、运维、迭代成本。
  • Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Hello.class); enhancer.setCallback(new TestAop()); Hello hello = (Hello)enhancer.create(); Enhancer enhancer1 = new Enhancer(); enhancer...
  • 一、createStore的第三个参数的定义(1)官方定义:createStore(reducer, [initialState], enhancer),第三个参数enhancer, 是一个组合 store creator 的高阶函数,返回一个新的强化过的 store creato
  • 小编来教您如何使用Aiseesoft Mac Video Enhancer让视频更加清晰。 1. 在Mac上添加视频文件 安装此视频增强软件并在Mac上运行。单击添加文件以加载视频。在这里,您可以批量导入视频文件。 2. 增强 单击主界面...
  • 整个过程如下:Cglib根据父类,Callback, Filter 及一些相关信息生成key. 然后根据key 生成对应的子类的二进制表现形式 使用ClassLoader装载对应的二进制,生成Class对象,并缓存 最后实例化Class对象,并缓存下面是...
  • 上一章讲到了使用JDK的Proxy实现AOP: ... 这一章我们讲另外一种方式,使用CGLIB实现AOP 使用CGLIB实现AOP功能 上一章我们已经说过,要产生某个对象的代理对象,这个对象必须实现一个接口,动态代理技术只能基于...
1 2 3 4 5 ... 20
收藏数 16,016
精华内容 6,406
关键字:

enhancer