CGLIB动态代理
- CGLIB动态代理非常强大、性能还挺厉害(点这里查看JDK与CGLIB的性能对比(引用))。
- 它的主要原理是:CGLIB通过字节码技术动态的生成业务类的子类,覆盖业务类的方法。并进行代理,因为采用的是继承方式,所以无法使用对final修饰的类进行代理。
光看原理肯定还是不是那么了解的,所以我们还是来写代码吧!
首先编写一个业务类
/**
* 人员信息服务
* @author wushuaiping
* @date 2018/3/14 下午10:44
*/
public class EmployeeServiceImpl {
public void insert(Employee employee){
System.out.println("我调用了业务方法往数据库插入了一条数据~");
}
}
再编写CGLIB动态代理的代码
- 首先需要去实现MethodInterceptor 方法拦截器。提供了intercept,方便在目标方法上进行切入。
- 再写一个获取代理对象的方法,该方法中需要使用到Enhancer,CGLIB通过该增强器底层的字节码技术生成业务类的子类。并创建该子类的对象。
除了通过enhancer.create()通过无参构造器创建业务类代理对象以为还可以使用enhancer.create(Class[] argumentTypes, Object[] arguments)通过有参构造器来创建对象。具体方式请点击(引用)
/**
* CGLIB动态代理
* @author wushuaiping
* @date 2018/3/14 下午10:50
*/
public class CGLIBProxy implements MethodInterceptor{
private Object target;
public Object newInstance(Object object){
this.target = object;
// 增强器
Enhancer enhancer = new Enhancer();
/* 生成被代理业务类(EmployeeServiceImpl)的子类;
* 就是因为这里继承的关系,被代理业务类就不能使用final修饰。
*/
enhancer.setSuperclass(this.target.getClass());
// 被代理业务类所有方法都会通过这里来调用
enhancer.setCallback(this);
// 创建代理对象 这个是创建无参构造器代理对象的方式
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
// 去调用父类中的方法
methodProxy.invokeSuper(o, objects);
after();
return null;
}
private void before(){
System.out.println("操作前的日志记录~~");
}
private void after(){
System.out.println("操作后的日志记录~~");
}
}
Test case
- 先后创建代理对象以及被代理的业务类对象
- 然后使用代理对象调用newInstance获取业务类代理类的对象。
- 调用业务类代理对象的业务方法
public static void main(String[] args) {
CGLIBProxy proxy = new CGLIBProxy();
EmployeeServiceImpl employeeService = new EmployeeServiceImpl();
EmployeeServiceImpl proxySer = (EmployeeServiceImpl)proxy.newInstance(employeeService);
proxySer.insert(new Employee());
}
运行结果
操作前的日志记录~~
我调用了业务方法往数据库插入了一条数据~
操作后的日志记录~~
来讲讲优缺点吧:
- CGLIB的功能还是蛮强大的,可以不用实现接口也可进行动态代理。但是缺点也很明显,因为底层通过继承业务类的方式来进行代理,所以业务类不能使用final修饰。