前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java动态代理和静态代理的实现

java动态代理和静态代理的实现

作者头像
IT云清
发布2019-01-22 15:09:41
4170
发布2019-01-22 15:09:41
举报
文章被收录于专栏:IT云清

代理模式:为其他对象提供一种代理以控制目标对象的访问,在某些情况下, 一个对象不适合或者不能直接引用另外一个对象,代理对象可以在这个客户类和目标对象中起到一个桥梁作用。

简单来说,代理对象的使用,是在不修改原有目标对象的基础上,增强原有目标对象的功能逻辑。

代理的实现有两种,静态代理和动态代理,而动态代理,又分为jdk动态代理和cglib动态代理。

本文目录:
  • 1.静态代理的实现
  • 2.jdk动态代理的实现
  • 3.cglib动态代理的实现

1.静态代理

需要目标类实现接口,代理类和目标类实现相同的接口,静态代理,是有代理类的,而动态代理是没有的。

1.1定义接口类UserService
代码语言:javascript
复制
package com.java4all.test_proxy_static;

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:接口
 */
public interface UserService {

    String doFirst();

    void doSecond();
}
1.2定义接口类的实现类

也就是我们的目标类,我们需要增强的类

代码语言:javascript
复制
package com.java4all.test_proxy_static;

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:接口实现类  目标类,等待增强
 */
public class UserServiceImpl implements UserService{
    @Override
    public String doFirst() {
        System.out.println("执行了doFirst()方法");
        return "iloveyou";
    }

    @Override
    public void doSecond() {
        System.out.println("执行了doSecond()方法");
    }
}
1.3定义目标类的代理类

要和目标类实现相同的接口,在此代理类的方法中进行增强

代码语言:javascript
复制
package com.java4all.test_proxy_static;

import org.springframework.stereotype.Service;

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:静态代理  有代理类
 * 在代理类中增强目标类的方法
 */
@Service
public class UserServiceImplProxy implements UserService{

    @Override
    public String doFirst() {
        //调用目标类的原始方法
        UserServiceImpl userService = new UserServiceImpl();
        String str = userService.doFirst();
        //增强逻辑 这里以字母转换为例
        str = str.toUpperCase();
        return str;
    }

    @Override
    public void doSecond() {
        UserService userService = new UserServiceImpl();
        userService.doSecond();
    }
}
1.4测试

测试一下,原本目标类中有个方法是返回iloveyou,在代理类中,我们对此方法进行了增强,将字母转为了大写进行返回。

代码语言:javascript
复制
package com.java4all.test_proxy_static;

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:测试静态代理
 */
public class TestProxy {

    public static void main(String[]args){
        test1();
        System.out.println("--------------");
        test2();
    }

    /**
     * 调用原有的目标对象来实现功能
     */
    public static void test1(){
        UserService userService = new UserServiceImpl();
        System.out.println(userService.doFirst());
        userService.doSecond();
    }

    /**
     * 调用代理对象来实现功能
     */
    public static void test2(){
        UserService userServiceImplProxy = new UserServiceImplProxy();
        System.out.println(userServiceImplProxy.doFirst());
        userServiceImplProxy.doSecond();
    }
}

测试结果如下:

代码语言:javascript
复制
执行了doFirst()方法
iloveyou
执行了doSecond()方法
--------------
执行了doFirst()方法
ILOVEYOU
执行了doSecond()方法

2.jdk动态代理

jdk动态代理的原理是,和目标类实现共同的接口,由Proxy.newProxyInstance生成一个代理对象,在代理对象调用方法时,在invoke方法中增强。

jdk动态代理,不需要代理类,他的实现必须是要求目标类实现了某个接口,然后代理对象和目标类实现了相同的接口。

2.1定义接口
代码语言:javascript
复制
package com.java4all.test_proxy_jdk;

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:接口
 */
public interface UserService {

    String doFirst();

    void doSecond();
}
2.2定义实现类

也就是需要增强的目标类

代码语言:javascript
复制
package com.java4all.test_proxy_jdk;

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:接口实现类  目标类,等待增强
 */
public class UserServiceImpl implements UserService {
    @Override
    public String doFirst() {
        System.out.println("执行了doFirst()方法");
        return "iloveyou";
    }

    @Override
    public void doSecond() {
        System.out.println("执行了doSecond()方法");
    }
}
2.3测试jdk动态代理
代码语言:javascript
复制
package com.java4all.test_proxy_jdk;

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

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:jdk动态代理
 * 没有代理类
 * 由Proxy.newProxyInstance生成一个代理对象,在调用方法时,在invoke方法中增强
 * 要求:目标类存在接口,目标类和代理对象要实现相同的接口
 */
public class TestProxy {

    public static void main(String[]args){
       test1();
    }

    public static void test1(){
        //目标类对象
        UserService target = new UserServiceImpl();

        /**jdk动态代理,没有代理类,由Proxy.newProxyInstance生成一个代理对象*/
        UserService userService = (UserService)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 invoke = method.invoke(target, args);
                        if(invoke != null){
                            return invoke.toString().toUpperCase();
                        }
                        return null;
                    }
                });
        System.out.println(userService.doFirst());
        userService.doSecond();
    }

}

结果:

代码语言:javascript
复制
执行了doFirst()方法
ILOVEYOU
执行了doSecond()方法

3.cglib动态代理

cglib动态代理的原理是,生成目标类的子类,在子类中进行增强,这个子类对象就是代理对象。

使用cglib代理时,要求目标类必须可以被继承,即没有用final修饰。

CGLIB(code generation Library)是一个开源项目,是一个强大的,高性能的,高质量的代码生成类库。他可以在运行期间拓展和增强java类,Spring用它来实现AOP编程。

3.1目标类UserService

不需要实现接口

代码语言:javascript
复制
package com.java4all.test_proxy_cglib;

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:目标类,没有实现接口,等待增强
 */
public class UserService {

    public String doFirst() {
        System.out.println("执行了doFirst()方法");
        return "iloveyou";
    }

    public void doSecond() {
        System.out.println("执行了doSecond()方法");
    }
}
3.2代理工厂

用来生成目标类的代理对象,此类需要实现MethodInterceptor

代码语言:javascript
复制
package com.java4all.test_proxy_cglib;

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

import java.lang.reflect.Method;

/**
 * author:lightClouds917
 * date:2018/10/7
 * description:返回目标类的代理对象
 * 需要实现MethodInterceptor
 */
public class MyCglib implements MethodInterceptor{

    private UserService target;

    public MyCglib(UserService target) {
        this.target = target;
    }

    /**
     * 返回目标类的代理对象
     * @return
     */
    public UserService MyCglibCreator(){
        Enhancer enhancer = new Enhancer();
        //指定父类,即目标类  cglib原理:子类增强父类
        enhancer.setSuperclass(UserService.class);
        //设置回调接口 当前类继承了MethodInterceptor,
        //此接口public interface MethodInterceptor extends Callback
        enhancer.setCallback(this);
        //create创建cglib动态代理对象
        return (UserService)enhancer.create();
    }


    //回调接口的方法  代理对象执行目标方法时,会触发该方法
    @Override
    public Object intercept(Object o,
                            Method method,
                            Object[] objects,
                            MethodProxy methodProxy) throws Throwable {
        Object invoke = method.invoke(target, objects);
        if(invoke != null){
            return invoke.toString().toUpperCase();
        }
        return invoke;
    }
}
3.3测试cglib动态代理
代码语言:javascript
复制
package com.java4all.test_proxy_cglib;


/**
 * author:lightClouds917
 * date:2018/10/7
 * description:cglib动态代理
 */
public class TestProxy {

    public static void main(String[]args){
       test1();
    }

    public static void test1(){
        UserService target = new UserService();

        //调用工厂类获取代理对象
        MyCglib myCglib = new MyCglib(target);
        UserService userService = myCglib.MyCglibCreator();

        System.out.println(userService.doFirst());
        userService.doSecond();
    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年10月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本文目录:
  • 1.静态代理
    • 1.1定义接口类UserService
      • 1.2定义接口类的实现类
        • 1.3定义目标类的代理类
          • 1.4测试
          • 2.jdk动态代理
            • 2.1定义接口
              • 2.2定义实现类
                • 2.3测试jdk动态代理
                • 3.cglib动态代理
                  • 3.1目标类UserService
                    • 3.2代理工厂
                      • 3.3测试cglib动态代理
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档