java 进阶一:代理和动态代理

Posted blackx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 进阶一:代理和动态代理相关的知识,希望对你有一定的参考价值。

静态代理:

  定义顶级接口:Iservice

//目标类和代理类都实现该接口
public interface Iservice {
    public String server();
}

  定义目标类:ServiceImp 实现 Iservice接口

// 目标类
public class ServiceImp implements Iservice {
    @Override
    public String server() {
        return "hello";
    }
}

  定义代理类:ServiceProxy 实现 Iservice 接口,将目标类中目标方法的返回值变为大写字符

// 代理类
public class ServiceProxy implements Iservice {
    
    Iservice target;
    
    public ServiceProxy() {
    }
    
    public ServiceProxy(Iservice target) {
        this.target = target;
    }

    @Override
    public String server() {
        return target.server().toUpperCase();
    }
}

测试:

public class Test {
    public static void main(String[] args) {
        Iservice target=new ServiceImp();
        Iservice proxy=new ServiceProxy(target);
        System.out.println(proxy.server());
    }
}

 

动态代理的两种实现方式

  1、使用JDK的Proxy实现代理,要求目标类和代理类实现相同的接口。若目标类不存在接口,则无法使用该方式实现。

  2、对于无接口的类,需要使用CGLIB来实现代理。CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类就是代理对象。因此,使用CGLIB生成动态代理,要求目标类必须能被继承,即不能是final修饰的类。

  CGLIB(Code Generation Library)是一个开源项目,是一个强大的、高性能的、高质量的代码生成类库。它可以在运行期间扩展和增强java类。Hibernate用它来实现持久对象的字节码的动态生成,Spring用它来实现AOP编程。CGLIB包的底层是通过使用字节码处理框架ASW(Java字节码处理框架),来转换字节码并生成新的类。CGLIB是通过对字节码进行增强来生成代理的。

 

相关实例代码:

  1、Proxy实现:

public class Test {
    public static void main(String[] args) {
        // 定义目标对象
        Iservice target=new ServiceImp();
        // 定义目标对象的代理对象
        Iservice myproxy=(Iservice) Proxy.newProxyInstance(
                target.getClass().getClassLoader(), // 目标类的类加载器
                target.getClass().getInterfaces(), //目标类实现的接口
                new InvocationHandler() {
            // proxy:代理对象
            // method:目标方法
            // args:目标方法的参数
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) 
                    throws Throwable {
                Object result=method.invoke(target, args);
                if ("server".equals(method.getName())) {
                    result = result.toString().toUpperCase();
                }
                return result;
            }
            
        });
        System.out.println(myproxy.server());
    }
}

  2、CGLIB实现:

  定义目标类:Service

public class Service {
    public String server(){
        return "hello";
    }
}

  创建cglib代理:

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {
    private Service target;
    public CglibProxy() {
    }
    public CglibProxy(Service target){
        this.target=target;
    }
    // 创建cglib代理对象
    public Service myProxy(){
        Service service=new Service();
        Enhancer enhancer=new Enhancer();
        // 指定父类,即要增强的目标类
        enhancer.setSuperclass(Service.class);
        // 指定回调接口对象
        enhancer.setCallback(this);
        // 创建cglib代理对象
        return (Service) enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        Object result=method.invoke(target, args);
        if ("server".equals(method.getName())) {
            result = result.toString().toUpperCase();
        }
        return result;
    }
}

   测试:

public class Test {
    public static void main(String[] args) {
        // 创建目标对象
        Service target=new Service();
        // 创建目标对象的代理对象
        Service proxy=new CglibProxy(target).myProxy();
        System.out.println(proxy.server());
    }
}

 

以上是关于java 进阶一:代理和动态代理的主要内容,如果未能解决你的问题,请参考以下文章

##(⊙o⊙)值得收藏的JavaSE万字进阶版(⊙o⊙)##JavaSE 高级反射-动态代理-设计模式-JVM篇

java进阶--动态代理全面理解

Java开发经典实战!java的动态代理和静态代理

动态代理

(java反射-JDK动态代理)+CGLIB动态代理

Java代理(jdk静态代理动态代理和cglib动态代理)