CGLIB 实现代理对象API

转载自 CGLIB 实现代理对象API


1. 加入库cglib库
cglib-2.2.jar
asm库(cglib 需要asm库,如果没有加入asm的jar文件,就会报asm错误)
asm-3.1.jar
 2. 定义CGLIB操作类
package com.machome.cglibtest;

import java.lang.reflect.Method;
import com.machome.model.StuService;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CGlibProxyFactory implements MethodInterceptor {
    private Object targetObject;

   
    public Object createProxyInstance(Object targetObject){
       this.targetObject = targetObject;    //传入用户类
      
       Enhancer enhancer = new Enhancer();          //Enhancer是cglib的核心类
      
         // 将用户类设为 Enhancer对象的superclass属性,,即设为 Enhancer对象的父类
       enhancer.setSuperclass(this.targetObject.getClass());     
         // 设 Enhancer对象的Callbacks属性,要求必须是Callback接口类型
       enhancer.setCallback(this);
      
       return enhancer.create();  //生成代理对象
    }
   
   
    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2,
            MethodProxy arg3) throws Throwable {
        StuService bean = (StuService)this.targetObject;
        Object result = null;       
        if(!arg1.getName().equals("save")&&(bean.findAll().size()==0))
        {  // 如果方法名不是save(即是get,update,delete方法),而同时实例的列表为空,就不执行方法,而是告警
            System.out.println("list is null,method is stoped");           
        }else{
        //执行代理方法,传入实例和方法参数
        result = arg3.invoke(targetObject, arg2);                
        }
        return result;      
    }
}
3.测试代码测试代码:
        CGlibProxyFactory factory = new CGlibProxyFactory();
        StuService bean = (StuService)factory.createProxyInstance(
                            new StuService());
       
        List<Stu> stuList = bean.findAll();
        if(stuList!=null){
        for(Stu temp:stuList)
            System.out.println(temp.getId()+":"+temp.getName());
        System.out.println("finished");

执行结果:
list is null,method is stoped            //bean.findAll()下边的语句都没执行)


cglib 执行intercept()的原理:
  • 自定义类应该实现MethodInterceptor接口,,覆写 intercept()方法
public interface MethodInterceptor extends Callback
{
    public abstract Object intercept(Object obj, Method method, Object aobj[], MethodProxy methodproxy)
        throws Throwable;
}
  • Enhancer对象设其Callback对象(实际是Callbacks对象,一个数组,但我们经常只设一个)    
 enhancer.setCallback(Callback callback);
  • 这样当Enhancer对象建立代理对象的时候,就会在执行用户调用的方法前,先执行intercept()方法

常见的两种不同的实现MethodInterceptor接口的cglib编程
  • 1.自定义类直接实现MethodInterceptor接口,覆写 intercept()方法
public class CGlibProxyFactory implements MethodInterceptor {
    public Object createProxyInstance(Object targetObject){
          ...
       enhancer.setCallback(this);
      ...
     }
   
    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2,
            MethodProxy arg3) throws Throwable {
            ...
            }   
}
  • 2.另一种方式,定义一个内部类,该类实现MethodInterceptor接口,覆写intercept()方法
public class CGlibProxyFactory1 {

    public Object createProxyInstance(Object targetObject){
     ...
     enhancer.setCallback(new MethodInterceptorImpl());
     ...
     }

       private class MethodInterceptorImpl implements MethodInterceptor {

        @Override
        public Object intercept(Object obj, Method method, Object[] aobj,
                MethodProxy methodproxy) throws Throwable {
                ...
                }
   }
 } 


注意 public Object intercept(Object obj, Method method, Object[] aobj,MethodProxy methodproxy)方法的第一个参数obj有很大问题
intercept方法里的主要动作是执行invoke方法
有两种执行方法:
法1:将参数obj传入invokeSuper()方法:
return methodproxy.invokeSuper(obj, aobj);

obj应该是传入Enhancer 对象的用户对象
(即上边enhancer.setSuperclass(this.targetObject.getClass()))
法2:或者将传入Enhancer对象前的原始用户对象传入invoke()方法:
return methodproxy.invoke(targetObject, aobj);

实际工作中发现,参数obj不态好用. 如果你想intercept()方法中调用对象执行一些方法的话,obj会出stackOverflow这样的异常
如下面的例子:
    public Object intercept(Object obj, Method method, Object[] aobj,
            MethodProxy methodproxy) throws Throwable {
        StuService bean = (StuService)obj;
        Object result = null;       
        if(!method.getName().equals("save")&&(bean.findAll().size()==0))
        {  // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警
            System.out.println("list is null,method is stoped");           
        }else{
        result = methodproxy.invokeSuper(obj, aobj);
        }
        return result;
    }
执行时会出线面的异常:
Exception in thread "main" java.lang.StackOverflowError
改成下面就好了:       
    public Object intercept(Object obj, Method method, Object[] aobj,
            MethodProxy methodproxy) throws Throwable {
        StuService bean = (StuService)this.targetObject;  //从外部传入的原始用户实例
        Object result = null;       
        if(!method.getName().equals("save")&&(bean.findAll().size()==0))
        {  // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警
            System.out.println("list is null,method is stoped");           
        }else{
        result = methodproxy.invoke(targetObject, aobj);
        }
        return result;
}


cglib 在 spring,hibernate中的应用
Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制
Spring则是利用cglib来实现动态代理。

spring,hibernate同时支持proxy类动态代理和cglib,二者的区别
proxy动态代理只能对 实现了接口 的类生成代理,而不能针对类
CGLIB是针对类生成代理,主要是对用户类生成一个子类

spring 下缺省是支持proxy 动态代理,如何强制使用CGLIB生成代理?
spring 主要在两个地方使用代理
AOP:
<aop:aspectj-autoproxy proxy-target-class="true"/> 
Transaction:
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

1. 加入库cglib库
cglib-2.2.jar
asm库(cglib 需要asm库,如果没有加入asm的jar文件,就会报asm错误)
asm-3.1.jar
 2. 定义CGLIB操作类
package com.machome.cglibtest;

import java.lang.reflect.Method;
import com.machome.model.StuService;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CGlibProxyFactory implements MethodInterceptor {
    private Object targetObject;

   
    public Object createProxyInstance(Object targetObject){
       this.targetObject = targetObject;    //传入用户类
      
       Enhancer enhancer = new Enhancer();          //Enhancer是cglib的核心类
      
         // 将用户类设为 Enhancer对象的superclass属性,,即设为 Enhancer对象的父类
       enhancer.setSuperclass(this.targetObject.getClass());     
         // 设 Enhancer对象的Callbacks属性,要求必须是Callback接口类型
       enhancer.setCallback(this);
      
       return enhancer.create();  //生成代理对象
    }
   
   
    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2,
            MethodProxy arg3) throws Throwable {
        StuService bean = (StuService)this.targetObject;
        Object result = null;       
        if(!arg1.getName().equals("save")&&(bean.findAll().size()==0))
        {  // 如果方法名不是save(即是get,update,delete方法),而同时实例的列表为空,就不执行方法,而是告警
            System.out.println("list is null,method is stoped");           
        }else{
        //执行代理方法,传入实例和方法参数
        result = arg3.invoke(targetObject, arg2);                
        }
        return result;      
    }
}
3.测试代码测试代码:
        CGlibProxyFactory factory = new CGlibProxyFactory();
        StuService bean = (StuService)factory.createProxyInstance(
                            new StuService());
       
        List<Stu> stuList = bean.findAll();
        if(stuList!=null){
        for(Stu temp:stuList)
            System.out.println(temp.getId()+":"+temp.getName());
        System.out.println("finished");

执行结果:
list is null,method is stoped            //bean.findAll()下边的语句都没执行)


cglib 执行intercept()的原理:
  • 自定义类应该实现MethodInterceptor接口,,覆写 intercept()方法
public interface MethodInterceptor extends Callback
{
    public abstract Object intercept(Object obj, Method method, Object aobj[], MethodProxy methodproxy)
        throws Throwable;
}
  • Enhancer对象设其Callback对象(实际是Callbacks对象,一个数组,但我们经常只设一个)    
 enhancer.setCallback(Callback callback);
  • 这样当Enhancer对象建立代理对象的时候,就会在执行用户调用的方法前,先执行intercept()方法

常见的两种不同的实现MethodInterceptor接口的cglib编程
  • 1.自定义类直接实现MethodInterceptor接口,覆写 intercept()方法
public class CGlibProxyFactory implements MethodInterceptor {
    public Object createProxyInstance(Object targetObject){
          ...
       enhancer.setCallback(this);
      ...
     }
   
    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2,
            MethodProxy arg3) throws Throwable {
            ...
            }   
}
  • 2.另一种方式,定义一个内部类,该类实现MethodInterceptor接口,覆写intercept()方法
public class CGlibProxyFactory1 {

    public Object createProxyInstance(Object targetObject){
     ...
     enhancer.setCallback(new MethodInterceptorImpl());
     ...
     }

       private class MethodInterceptorImpl implements MethodInterceptor {

        @Override
        public Object intercept(Object obj, Method method, Object[] aobj,
                MethodProxy methodproxy) throws Throwable {
                ...
                }
   }
 } 


注意 public Object intercept(Object obj, Method method, Object[] aobj,MethodProxy methodproxy)方法的第一个参数obj有很大问题
intercept方法里的主要动作是执行invoke方法
有两种执行方法:
法1:将参数obj传入invokeSuper()方法:
return methodproxy.invokeSuper(obj, aobj);

obj应该是传入Enhancer 对象的用户对象
(即上边enhancer.setSuperclass(this.targetObject.getClass()))
法2:或者将传入Enhancer对象前的原始用户对象传入invoke()方法:
return methodproxy.invoke(targetObject, aobj);

实际工作中发现,参数obj不态好用. 如果你想intercept()方法中调用对象执行一些方法的话,obj会出stackOverflow这样的异常
如下面的例子:
    public Object intercept(Object obj, Method method, Object[] aobj,
            MethodProxy methodproxy) throws Throwable {
        StuService bean = (StuService)obj;
        Object result = null;       
        if(!method.getName().equals("save")&&(bean.findAll().size()==0))
        {  // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警
            System.out.println("list is null,method is stoped");           
        }else{
        result = methodproxy.invokeSuper(obj, aobj);
        }
        return result;
    }
执行时会出线面的异常:
Exception in thread "main" java.lang.StackOverflowError
改成下面就好了:       
    public Object intercept(Object obj, Method method, Object[] aobj,
            MethodProxy methodproxy) throws Throwable {
        StuService bean = (StuService)this.targetObject;  //从外部传入的原始用户实例
        Object result = null;       
        if(!method.getName().equals("save")&&(bean.findAll().size()==0))
        {  // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警
            System.out.println("list is null,method is stoped");           
        }else{
        result = methodproxy.invoke(targetObject, aobj);
        }
        return result;
}


cglib 在 spring,hibernate中的应用
Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制
Spring则是利用cglib来实现动态代理。

spring,hibernate同时支持proxy类动态代理和cglib,二者的区别
proxy动态代理只能对实现了接口的类生成代理,而不能针对类
CGLIB是针对类生成代理,主要是对用户类生成一个子类

spring 下缺省是支持proxy 动态代理,如何强制使用CGLIB生成代理?
spring 主要在两个地方使用代理
AOP:
<aop:aspectj-autoproxy proxy-target-class="true"/> 
Transaction:
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329208.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android java split_Java中的split函数的用法

Java中的 split 函数是用于按指定字符(串)或正则去分割某个字符串&#xff0c;结果以字符串数组形式返回&#xff1b;例如:String str"1234abc";String[] a str.split("");System.out.println("处理结果: "a[0]","a[1]); //输出的…

第二章指南(4.2)添加 Controller

原文&#xff1a;Adding a controller翻译&#xff1a;娄宇(Lyrics)校对&#xff1a;刘怡(AlexLEWIS)、何镇汐、夏申斌、孟帅洋(书缘) Model-View-Controller (MVC) 架构模式将一个应用程序分离成三个主要的组件&#xff1a; Model、View 以及Controller 。 MVC 模式帮助你创建…

jdk和cglib简单理解

转载自 jdk和cglib简单理解之前使用cglib的时候不需要将classLoader作为参数传入&#xff0c;但动态代理却要&#xff0c;带着这个疑惑进入这个方法&#xff1a;Proxy.newProxyInstance(classLoader, interfaces, InvocationHandler)要在classLoader里去找interfaces&#xff0…

mysql引擎总结_MySQL存储引擎对比总结

存储引擎是数据库的核心&#xff0c;对于mysql来说&#xff0c;存储引擎是以插件的形式运行的。虽然mysql支持种类繁多的存储引擎&#xff0c;但是常用的就那么几种。这篇文章主要是对其进行一个总结和对比。一、引言在mysql5之后&#xff0c;支持的存储引擎有十几个&#xff0…

DotNet Core 介绍

前言 asp.net core rtm 6月底即将发布&#xff0c;自己也想着为社区做点共享&#xff0c;刚好最近不太忙&#xff0c;看到社区的小伙伴们都在为dotnet core的推广而贡献力量&#xff0c;项目中刚好在用rc2版本&#xff0c;就多写些文章来帮助那些还在学习的朋友们吧。 目录 dot…

jdbc java_Java中使用JDBC

JDBC简介JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API&#xff0c;可以为多种关系数据库提供统一访问&#xff0c;它由一组用Java语言编写的类和接口组成。本文中中使用的数据库数据库软件&#xff1a;MySQL5.6数据库&#xff1a;test表&…

动态代理proxy与CGLib的区别

转载自 动态代理proxy与CGLib的区别昨天被人问及动态代理与CGlib的区别&#xff0c;赶紧回顾一下&#xff1a; 什么是代理&#xff1f;静态代理与动态代理静态代理实例JDK动态代理实例CGLib 简介CGLib 与JDK动态代理的区别代理模式是Java中常见的一种模式&#xff0c;英文名字叫…

【干货】”首个“ .NET Core 验证码组件

前言 众所周知&#xff0c;Dotnet Core目前没有图形API&#xff0c;以前的System.Drawing程序集并没有包含在Dotnet Core 1.0环境中。不过在dotnet core labs项目里可以见到MS已经在移植这个项目&#xff0c;不过目前的版本只能在Windows上和NET541或DNX环境中才可以使用。 不过…

java 招聘要求_Java程序员如何进阶,一般招聘都有哪些要求?

作为当前市场上应用领域最广、人才需求最大的编程语言&#xff0c;Java一直是人们入行IT行业的选择。然而&#xff0c;随着大批量的人涌入Java开发行业&#xff0c;企业的招聘门槛也在无形中抬高&#xff0c;提升专业技能成为新手Java程序员实现升职加薪的有效途径。分析各大招…

朝花夕拾——Java的synthetic修饰词

转载自 朝花夕拾——Java的synthetic修饰词Ok&#xff0c;目前为止&#xff0c;我还只是Android coder&#xff0c;一切对其他的学习都是以Android 为主线的支线任务。所以为什么会提到这个方法呢&#xff1f;是来自于google官方的性能建议文档的这样一句话&#xff1a;Consid…

asp.net MVC 应用程序的生命周期

首先我们知道http是一种无状态的请求&#xff0c;他的生命周期就是发出请求开始&#xff0c;到得到响应结束。那么MVC应用程序从发出请求到获得响应&#xff0c;都做了些什么呢&#xff1f; 本文我们会详细讨论MVC应用程序的生命周期和一个请求&#xff0c;从一个控件到另一个控…

java 刷新界面_利用java如何实现在删除信息后刷新页面功能

利用java如何实现在删除信息后刷新页面功能发布时间&#xff1a;2020-11-17 14:25:49来源&#xff1a;亿速云阅读&#xff1a;74作者&#xff1a;Leah这篇文章给大家介绍利用java如何实现在删除信息后刷新页面功能&#xff0c;内容非常详细&#xff0c;感兴趣的小伙伴们可以参考…

Java中的synthetic

转载自 Java中的synthetic 有synthetic标记的field和method是class内部使用的&#xff0c;正常的源代码里不会出现synthetic field。小颖编译工具用的就是jad.所有反编译工具都不能保证完全正确地反编译class。所以你不能要求太多。 下面我给大家介绍一下synthetic 下面的例子…

java凯撒密码_JAVA凯撒密码 选择问题

以下是加密和解密的程序&#xff1a;加密&#xff1a;importjava.io.*;classJiami26{publicstaticvoidmain(Stringargs[])throwsIOException{charb[];//存放密文BufferedReaderbr2newBufferedReader(newIn...以下是加密和解密的程序&#xff1a;加密&#xff1a;import java.io…

synthetic Java合成类型

转载自 synthetic Java合成类型Synthetic看Class源码的时候&#xff0c;看到有个关键字Synthetic以及isSynthetic()方法&#xff0c;遂有兴趣查阅了一番。   一开始以为&#xff0c;就是复合类型&#xff08;引用类型&#xff09;&#xff0c;也就是非基本类型&#xff0c;…

Java 反射机制深入研究

转载自 Java 反射机制深入研究Java反射机制深入研究Java 反射是Java语言的一个很重要的特征&#xff0c;它使得Java具体了“动态性”。在Java运行时环境中&#xff0c;对于任意一个类&#xff0c;能否知道这个类有哪些属性和方法&#xff1f;对于任意一个对象&#xff0c;能否…

RAML用户应遵循的C#与Web API代码生成模式

在过去几年间&#xff0c;REST规范的各种语言正在逐渐流行起来&#xff0c;例如RAML、Swagger以及API Blueprint。但这些语言的主要范畴在于客户端工具&#xff0c;主要用于生成JavaScript或TypeScript文件、模拟对象&#xff08;mock&#xff09;&#xff0c;以及对应的客户端…

wxpython使用folium_wxPython实现文本框基础组件

本文实例为大家分享了wxPython实现文本框的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下#-*- coding:utf-8 -*-"""#############################################StaticText 参数说明 --即 labelparent&#xff1a; -- 父窗口部件。id&#xff1a;…

教你实践ASP.NET Core Authorization(免看文档教程)

准备 创建一个名为AuthorizationForoNetCore的&#xff08;web&#xff09;解决方案,选择Empty模板添加相关nuget包引用Microsoft.AspNetCore.Mvc&#xff08;选择最新版本&#xff09;编辑Startup.cs文件&#xff0c;添加mvcservice并进行默认路由配置 添加Controllers文件夹&…

Class类中的getEnclosingXX、getDeclaredXX

转载自 Class类中的getEnclosingXX、getDeclaredXX一、getEnclosingXX getEnclosingClass():该类是在那个类中定义的&#xff0c; 比如直接定义的内部类或匿名内部类 getEnclosingConstructor()&#xff1a;该类是在哪个构造函数中定义的&#xff0c;比如构造方法中定义的匿名…