一 动态代理-cglib
程序在运行期间,为被代理对象生成代理对象,并且没有静态代理,和jdk动态代理实现公共接口的苛刻条件,基于cglib的动态代理是在
运行期间为被代理对象生成一个子类作为代理对象,并重写了父类的所有方法(由于是重写的父类方法,父类final所修饰的的方法将不会被
重写使用),代理类中的所有方都只要被调用都将会被拦截,当方法被拦截后增强器会将此类的信息及方法发参数等信息发送到,初始化
增强器(Enhancer())时指定的方法拦截后回调函数(即setCallBack)中执行
cglib是一个强大的高性能的代码生成包
二 代码演示
cdlib中此interface是 可以不存在的
package com.mybatis.excample.dynamicProxy.cglib;
public interface PhoneService{
void addPhone(String name,String id);
void getPhone(String id);
}
被代理类
package com.mybatis.excample.dynamicProxy.cglib;
/**
* Created by Administrator on 2018/1/26.
*/
public class PhoneServiceImpl implements PhoneService {
@Override
public void addPhone(String name, String id) {
System.out.println("添加手机 id为:" + id + " 手机名称为:" + name);
}
@Override
public void getPhone(String id) {
System.out.println("获取手机通过手机id为:" + id);
}
}
注册自定义方法拦截器
package com.mybatis.excample.dynamicProxy.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 自定义方法拦截器
*/
public class MyMethodIterator implements MethodInterceptor {
private Class target;
//覆盖默认的构造,使用被代理类初始化拦截器对象
public MyMethodIterator(Class target){
this.target=target;
}
/**
* 使用cdlib(Code Generation Library)实现动态代理
* 底层使用asm字节码生成框架生成 代理类的子类并重写了父类的所有方法(由于是子类重写父类,父类中final修饰的方法将不能被重写)
* @return
*/
public Object getInstance(){
Enhancer enhancer = new Enhancer();//cglib增强器
enhancer.setCallback(this);//当代理的中的方法被调用后需要指明跳转到的自定义方法拦截器
enhancer.setSuperclass(target);//指定此代理类的 父类(被代理类)
return enhancer.create();//返回一个被代理类的子类
}
/**
*
* @param obj 当前代理类
* @param method 当前代理调用的方法
* @param args 当前方法所需参数
* @param proxy 当拦截的方法被调用 增强器会将代理类传递到自定义方法拦截器中 proxy拥有调用父类中的实际执行方法
* @return 返回增强后的结果
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object result=null;
System.out.println("类的名称是:"+obj.getClass().getName());
System.out.println("调用的方法名称是:"+method.getName());
for(Object parameter:args){
System.out.println("输入的参数类型为"+parameter.getClass().getName());
}
System.out.println("真正执行 before 增强");
result=proxy.invokeSuper(obj,args);
System.out.println("正在执行的是 after 增强");
return result;
}
}
测试入口
package com.mybatis.excample.dynamicProxy.cglib;
/**
* Created by Administrator on 2018/1/26.
*/
public class ClientText {
public static void main(String[] args) {
//指定被代理类 注册此类的方法拦截器并初始化
MyMethodIterator myMethodIterator = new MyMethodIterator(new PhoneServiceImpl().getClass());
//java的多态 强转类型
PhoneService service = (PhoneService) myMethodIterator.getInstance();
service.addPhone("华为", "21");
System.out.println("----------------");
service.getPhone("21");
}
}