CGLIB 实现代理对象

CGLIB 编程步骤:
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"/>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用CGLIB创建代理对象的主要步骤如下: 1. 定义一个类,并实现一个接口(或者继承一个类)作为目标类。 2. 在目标类中,定义一个方法。 3. 创建一个MethodInterceptor对象,用于拦截目标方法的执行。 4. 使用Enhancer创建代理对象,设置目标类、MethodInterceptor对象和其他相关参数。 5. 调用代理对象的方法,触发MethodInterceptor对象的intercept方法。 6. 在intercept方法中,可以通过MethodProxy对象调用目标方法,并在目标方法执行前后添加一些操作。 下面是一个示例代码: ```java public interface UserService { void addUser(String name, String password); } public class UserServiceImpl implements UserService { @Override public void addUser(String name, String password) { System.out.println("Add user: " + name); } } public class UserServiceInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Before method: " + method.getName()); Object result = proxy.invokeSuper(obj, args); System.out.println("After method: " + method.getName()); return result; } } public class ProxyDemo { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(new UserServiceInterceptor()); UserService userService = (UserService) enhancer.create(); userService.addUser("Alice", "123456"); } } ``` 运行上述代码,输出结果如下: ``` Before method: addUser Add user: Alice After method: addUser ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值