动态代理之jdk和cglib实现

1.Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:

        ①JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例,  生成目标类的代理对象。

        ②如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

(3)静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。

 InvocationHandler 的 invoke(Object  proxy,Method  method,Object[] args):proxy是最终生成的代理实例;  method 是被代理目标实例的某个具体方法;  args 是被代理目标实例某个方法的具体入参, 在方法反射调用时使用。

2.jdk动态代理示例

2.1定义接口类
public interface People {
    public void sayHello();
}
2.2实现类
public class Chinese implements People {
    @Override
    public void sayHello() {
        System.out.println("Chinese say hello.");
    }
}
2.3 jdk动态代理类实现invocationHandler
public class JdkProxy implements InvocationHandler {

    private Object object;

    public Object newProxy(Object object) {
        this.object = object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(object, args);
        System.out.println("-------- end ---------");
        return invoke;
    }
}

3.cglib动态代理

3.1 类的实现方法

public class User { public void sayNo(){ System.out.println("cglib proxy say no"); } }

3.2 cglib 实现MethodInterceptor接口

public class CglibProxy implements MethodInterceptor {
    // CGlib需要代理的目标对象
    private Object targetObject;

    public Object createCglibProxy(Object obj) {
        this.targetObject =obj;
        //创建一个动态类的对象 Enhancer是CGLIB的核心类通过它来创建代理对象
        Enhancer enhancer = new Enhancer();
        //设置父类,即设置需要进行功能增强的类
        enhancer.setSuperclass(obj.getClass());
        //设置回调方法
        enhancer.setCallback(this);
        //创建代理类并返回
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //前置增强方法... 
        System.out.println("前置增强方法,如日志,权限");
        //调用被代理对象的方法
        Object intercept = methodProxy.invokeSuper(o, objects);
        //后置增强方法...
        System.out.println("后置增强方法,如日志,权限");
        System.out.println("-------- end ---------");
        return intercept;
    }

}

4.测试

public static void main(String[] args) {
//        JDK动态代理只提供接口的代理,不支持类的代理。
        People p =(People)new JdkProxy().newProxy(new Chinese());
        p.sayHello();
//        jdk,不支持类的代理。所以如下这个方式不可以,会报错。
//        User p1 = (User) new JdkProxy().newProxy(new User());
//        p1.sayNo();        
        System.out.println("--------------------");
//      CGLIB来动态代理目标类
        User proxy = (User) new CglibProxy().createCglibProxy(new User());
        proxy.sayNo();
        People proxy1 = (People) new CglibProxy().createCglibProxy(new Chinese());
        proxy1.sayHello();
    }

5.cglib的优缺点

5.1缺点ava中有一种类是无法被继承的,那就是用final关键字定义的类。而cglib动态代理是基于继承来实现的,所以它唯一的不足就在这里----无法对 final类 进行代理。5.2 优点CGLIB实现动态代理,不需要接口!!!

6.引用依赖


    cglib
    cglib
    3.2.10

你可能感兴趣的:(动态代理之jdk和cglib实现)