博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java代理的三种方式
阅读量:4049 次
发布时间:2019-05-25

本文共 4275 字,大约阅读时间需要 14 分钟。

代理的理解

代理(Proxy)是一种设计模式,提供了对目标对象另一种访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在实现目标对象功能的基础上,增强额外的功能操作,即扩展目标对象的功能。

代理的分类:1、静态代理 2、动态代理 3、Cjlib代理

静态代理

由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类
接口

package com.linewell.staticproxy;public interface IUserDao{    public  void  save();}目标对象package com.linewell.staticproxy;public class UserDao implements IUserDao{    @Override    public void save() {        System.out.println("我是目标对象保存的方法");    }}代理对象package com.linewell.staticproxy;public class UserDaoProxy implements IUserDao {     //接收保存目标对象    private  IUserDao iUserDao;    public  UserDaoProxy(IUserDao iUserDao){        this.iUserDao=iUserDao;    }    @Override    public void save() {          System.out.println("开始事物。。。。");          iUserDao.save();          System.out.println("执行事物。。。。");    }}测试类package com.linewell.staticproxy;public class App {    public static void main(String[] args) {        //创建目标对象        UserDao userDao=new UserDao();        //把目标对象传给代理对象        UserDaoProxy userDaoProxy=new UserDaoProxy(userDao);        userDaoProxy.save();    }}

优点:在不改变目标对象的前提下,对目标对象进行扩展。

缺点:目标对象和代理对象都要实现相同的接口,如果说没有接口,那么就无法使用静态代理。

动态代理

也叫jdk代理,接口代理,代理对象不需要实现接口,代理的对象的生成是利用jdk的API通过反射的机制动态生成的。

反射:反射机制在运行状态中,对于任何一个类,可以知道他的所有属性和方法,对于任何一个对象,可以调用他的任意一个方法与属性

代理类:package com.linewell.dynamicproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyFactory implements InvocationHandler{    //定义一个目标对象    private Object target;    //给目标对象创建代理对象    public  ProxyFactory(Object target) {        this.target=target;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("------------------before------------------");        Object returnValue= method.invoke(target, args);        System.out.println("------------------after------------------");        return returnValue;    }    //创建获取代理的方法    public Object getProxy(){        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);    }}测试类:package com.linewell.dynamicproxy;import com.linewell.staticproxy.IUserDao;import com.linewell.staticproxy.UserDao;public class App {    public static void main(String[] args) {      //创建目标对象        IUserDao iUserDao=new UserDao();        System.out.println(iUserDao.getClass());        iUserDao.save();      //给目标对象创建代理对象       IUserDao proxy =(IUserDao)new ProxyFactory(iUserDao).getProxyInstance();       System.out.println(proxy.getClass());       proxy.save();    }}

总结:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理。

Cjlib代理
上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理,Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。,但因为采用的是继承,所以不能对final修饰的类进行代理。

目标类:package com.linewell.cjlib;public class Cat {    public void  eat(){        System.out.println("猫会钓鱼。。。。");    }    public void  run(){        System.out.println("猫会上树。。。。");    }}代理类:package com.linewell.cjlib;import net.sf.cglib.proxy.Callback;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 CatProxy implements MethodInterceptor{    //在内存中创建一个全新的类 没有类型 Enhancer类是CGLib中的一个字节码增强器    private  Enhancer enhancer = new Enhancer();    //创建代理对象的方法    public  Object createProxyObject(Class clazz){        enhancer.setSuperclass(clazz);        enhancer.setCallback(this);        //通过字节码技术动态创建子类实例        Object o=enhancer.create();        return o;    }    //intercept()方法拦截所有目标类方法的调用    //o表示目标类的实例    //method为目标类方法的反射对象    //MethodProxy为生成的代理类对方法的代理引用。    @Override    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("前置代理");        Object obj = proxy.invokeSuper(o, args);//调用类目标类方法        System.out.println("后置代理");        return obj;    }}测试类:package com.linewell.cjlib;public class App {    public static void main(String[] args) {        CatProxy catProxy = new CatProxy();        Cat cat = new Cat();        cat =(Cat) catProxy.createProxyObject(cat.getClass());        cat.eat();    }}

转载地址:http://nofci.baihongyu.com/

你可能感兴趣的文章
Xpath使用方法
查看>>
移动端自动化测试-Mac-IOS-Appium环境搭建
查看>>
Selenium之前世今生
查看>>
Selenium-WebDriverApi接口详解
查看>>
Selenium-ActionChains Api接口详解
查看>>
Selenium-Switch与SelectApi接口详解
查看>>
Selenium-Css Selector使用方法
查看>>
Linux常用统计命令之wc
查看>>
测试必会之 Linux 三剑客之 sed
查看>>
Socket请求XML客户端程序
查看>>
Java中数字转大写货币(支持到千亿)
查看>>
Java.nio
查看>>
函数模版类模版和偏特化泛化的总结
查看>>
VMware Workstation Pro虚拟机不可用解决方法
查看>>
最简单的使用redis自带程序实现c程序远程访问redis服务
查看>>
redis学习总结-- 内部数据 字符串 链表 字典 跳跃表
查看>>
iOS 对象序列化与反序列化
查看>>
iOS 序列化与反序列化(runtime) 01
查看>>
iOS AFN 3.0版本前后区别 01
查看>>
iOS ASI和AFN有什么区别
查看>>