码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-02-10 11:08:31      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:hiberna   ace   nat   ring   存在   ice   不能   父类   原理   

静态代理:

  定义顶级接口: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 进阶一:代理和动态代理

标签:hiberna   ace   nat   ring   存在   ice   不能   父类   原理   

原文地址:https://www.cnblogs.com/hypnus-ly/p/8429123.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!