代理学习

1、静态代理

测试类:

package com.example.demo.proxy;

public class StaticProxy implements UserDao {

    private UserDao userdao;

    public UserDao getUserdao() {
        return userdao;
    }

    public void setUserdao(UserDao userdao) {
        this.userdao = userdao;
    }

    @Override
    public void getUser() {
        System.out.println("代理类进入");
        userdao.getUser();
        System.out.println("代理类退出");
    }


    public static void main(String[] args) {
        StaticProxy sp = new StaticProxy();
        UserDao userDao = new UserDaoImpl();
        sp.setUserdao(userDao);
        sp.getUser();

    }
}

userdao:

package com.example.demo.proxy;

public interface UserDao {

    void getUser();
}

userdaoimpl:

package com.example.demo.proxy;

public class UserDaoImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("userdao impl");
    }
}

运行测试类:

代理类进入
userdao impl
代理类退出

2、jdk动态代理
测试类:

package com.example.demo.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxy1 {
    //维护一个被代理的类
    private Object obj;

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }

    public Object getInstance() {
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("进入proxy");
                        //invoke两个参数,obj原对象,args参数
                        method.invoke(obj, args);
                        System.out.println("退出proxy");
                        return null;
                    }
                });
    }

    public static void main(String[] args) {
        DynamicProxy1 dp1 = new DynamicProxy1();
        dp1.setObj(new UserDaoImpl());

        UserDao instance = (UserDao) dp1.getInstance();
        instance.getUser();
    }
}

userdao和userdaoimpl同上

运行测试类:

进入proxy
userdao impl
退出proxy
JDK动态代理局限性

通过反射类Proxy和InvocationHandler回调接口实现的jdk动态代理,要求委托类必须实现一个接口,但事实上并不是所有类都有接口,对于没有实现接口的类,便无法使用该方方式实现动态代理。

3、cglib动态代理

静态代理和jdk动态代理模式都是要求目标对象实现一个接口,
Cglib代理,也叫作子类代理,是基于asm框架,实现了无反射机制进行代理,利用空间来换取了时间,代理效率高于jdk ,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
它有如下特点:
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.
Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)
Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.
注意
需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
引入功能包后,就可以在内存中动态构建子类
代理的类不能为final,否则报错
目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
 
测试类:
package com.example.demo.proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 实现methodInterceptor方法,并重写interceptor方法
 */
public class CglibDynamicProxy implements MethodInterceptor {
    //维护一个被代理的对象
    private Object target;

    public Object getinstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        //回调方法指定当前类即可(实现了methodInterceptor接口的类)
        enhancer.setCallback(this);

        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib代理开始");
        Object invoke = method.invoke(target, objects);
        System.out.println("cglib代理结束");
        return invoke;
    }


    public static void main(String[] args) {
        CglibDynamicProxy cg = new CglibDynamicProxy();
        UserWithoutInterface u = new UserWithoutInterface();
        cg.setTarget(u);
        UserWithoutInterface instance = (UserWithoutInterface) cg.getinstance();
        instance.getuser();

    }


    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }
}

被代理对象UserwithoutInterface:

package com.example.demo.proxy;

public class UserWithoutInterface {

    public void getuser(){
        System.out.println("执行userwithoutInterface中的getuser方法");
    }
}

执行测试类结果:

cglib代理开始
执行userwithoutInterface中的getuser方法
cglib代理结束

参考:http://ifeve.com/java-reflection-11-dynamic-proxies/

原文地址:https://www.cnblogs.com/nxzblogs/p/11014986.html