使用cglib实现动态代理技术

Spring AOP(面向切面编程)使用了两种技术实现,一种是JDK自带的动态代理,另外一种是使用cglib字节码技术动态生成代理类。Spring是如何选择的了:

  • 如果目标对象实现了接口,默认情况先回选择使用JDK代理技术实现AOP,但是也可以强制使用cglib实现动态代理
  • 如果目标对象没有实现接口,则会采用cglib技术实现AOP

cglib创建某个动态代理类的模式是:

  • 查找目标类上所有非 final 的public类型的方法,将这些方法的定义转换成字节码
  • 将组成的字节码转换成相应的代理的class对象
  • 代理类实现MethodInterceptor接口,用来处理代理类上所有方法的请求(中介)

下面是代码:

定义一个通用接口,里面定义一些要拦截的方法

package com.minglangx.cglib;

/**
* 

  * @ClassName: UserService

  * @Description: 通用接口类

  * @author minglangx

  * @date 2017年8月19日 下午12:02:34

  *


  
*/
public interface UserService {

   String getName(String name);
   Integer getAge(int age);
   
}

定义一个目标对象,实现这个通用接口

package com.minglangx.cglib;
/**
 * 

  * @ClassName: UserServiceImpl

  * @Description: 目标对象

  * @author minglangx

  * @date 2017年8月19日 下午12:02:52

  *


  
 */
public class UserServiceImpl implements UserService {

    @Override
    public String getName(String name) {
        System.out.println("===getName===");
        return name;
    }

    @Override
    public Integer getAge(int age) {
        System.out.println("====getAge=====");
        return age;
    }

}

核心代理类,实现MethodInterceptor接口

package com.minglangx.cglib;

import java.lang.reflect.Method;
import java.util.Arrays;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 
 * 
 * @ClassName: CglibDemo
 * 
 * @Description: 代理类使用 Cglib实现动态代理
 * 
 * @author minglangx
 * 
 * @date 2017年8月18日 下午12:33:51
 *
 * 
 * 
 * 
 * 
 */
class CglibDemo implements MethodInterceptor {

    
    /**
     * Object obj 被代理的对象
     * Method method 被拦截的方法
     * Object[] objs 方法的参数
     * MethodProxy methodProxy  cglib中的代理对象
     * 
     * 
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] objs, MethodProxy methodProxy) throws Throwable {
        System.out.println("======before " + methodProxy.getSuperName() + "======");
        System.out.println("被拦截的方法名称-----" + method.getName());
        System.out.println("被拦截的方法参数-----" + Arrays.asList(objs));
        //invokeSuper(obj,objs) 第一个参数是被代理对象,第二个参数是参数集合
        Object objNew = methodProxy.invokeSuper(obj, objs);
        System.out.println("+++++before " + methodProxy.getSuperName() + "=====");
        return objNew;
    }
    
    
    
    
    

}

测试类

  • 使用 Enhancer().setSuperclass(目标对象); 设置要代理的对象
  • 使用 Enchancer.setCallback(目标对象); 将要代理对象的所有方法都转发到intercept()方法上进行拦截
  • 使用Enchancer.create();获取被代理的对象
package com.minglangx.cglib;

import net.sf.cglib.proxy.Enhancer;
import com.minglangx.cglib.UserService;
import com.minglangx.cglib.UserServiceImpl;

public class MainDemo {

    public static void main(String[] args) {

        CglibDemo cglibDemo = new CglibDemo();
        //cglib中的加强器,用来创建动态代理
        Enhancer enhancer = new Enhancer();
               //设置要动态创建的类
        enhancer.setSuperclass(UserServiceImpl.class);
        /*
         * 设置回调.这里相当于是对于代理类上所有方法的回调,都会调用CallBack,
         * 而Callback需要执行intercept()方法进行拦截
         */
        enhancer.setCallback(cglibDemo);
        
        //得到实际对象的接口类型,调用其方法
        UserService o =(UserService) enhancer.create();
        o.getName("zhangs");
        o.getAge(25);
        
        
        
        
    }

}

输出结果: 我们看到在被代理对象调用方法之前成功实现了方法的拦截

使用cglib实现动态代理技术_第1张图片
image.png

你可能感兴趣的:(使用cglib实现动态代理技术)