代理模式---动态代理之Cglib

使用JDK创建代理有一个限制,即它只能为接口创建代理实例,这一点我们可以从Proxy的接口newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h)方法签名中就看得很清楚。第二个入参interfaces就是需要代理实例实现的接口列表。

对于没有通过接口定义业务方法的类,如何动态创建代理实例呢?答案就是Cglib。

Cglib代理能在内存中构建一个子类对象从而实现对目标对象功能的扩展。

注意点:

1. 代理的类不能为final,否则报错

2. 目标对象的方法如果为final或static,那么就不会被拦截,即不会执行目标对象额外的业务方法。

 

目标类UserServiceImpl:

package com.ant.jdk8.proxy;

public class UserServiceImpl {

    public void deleteUser(){
        System.out.println("删除用户");
    }
    
}

代理类CglibProxy:

package com.ant.jdk8.proxy;

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 CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz){
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("---开始事务---");
        Object result = proxy.invokeSuper(obj,args);
        System.out.println("---提交事务---");
        return result;
    }
}

测试类App:

package com.ant.jdk8.proxy;

public class App {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        UserServiceImpl userService = (UserServiceImpl)proxy.getProxy(UserServiceImpl.class);
        userService.deleteUser();
    }
}

在Spring AOP的编程中,如果加入容器的目标对象有实现接口,用JDK代理;如果目标对象没有实现接口,用Cglib代理。

 

posted on 2019-02-16 22:44  shammgod_code  阅读(106)  评论(0编辑  收藏  举报

导航