动态代理-JDK和Cglib实现

动态代理

一、JDK

JDK实现动态代理类,被代理的类需实现接口。自动生成的代理类也会实现该接口。

定义接口

package com.test;

public interface User {
    public void talk();
    public void run();

}

被代理类

package com.test;

public class UserImpl implements User{

    @Override
    public void talk() {
        System.out.println("i am talking");
    }

    @Override
    public void run() {
        System.out.println("i am running");
    }

}

创建请求处理类(实现InvocationHandler接口)

package com.test;

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

public class MyInvocationHandler implements InvocationHandler{
    //关联代理对象
    private Object target;

    //参数为空的构造方法
    MyInvocationHandler(){
        super();
    }
    //通过构造函数的方式
    MyInvocationHandler(Object target){
        this.target=target;

    }
    /*proxy : 生成的代理类
     method : 代理方法对象
     args : 代理方法参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //前置逻辑
        System.out.println("before method");
        //代理执行所需方法
        Object result =method.invoke(target, args);
        //后置逻辑
        System.out.println("after method");
        //方法执行返回值
        return result;
    }

}

这里顺便说一下类与类之间的几种关系:

关系java中表现形式区分
泛化继承” extends “
实现接口实现” implements “
依赖类方法中的局部变量” uses a “
关联类成员变量” has “
聚合类成员变量” owns a “
组合类成员变量” is a part of”

关联、聚合、组合,变现形式一样,仅仅是逻辑上的区别。而上面的MyInvocationHandler类关联了Object 被代理对象。这是代理模式的核心之一。

测试

package com.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import org.junit.Test;
public class TestInvocation {
    /**
     * 
     * @throws NoSuchMethodException
     * @throws SecurityException
     * 使用jdk自带的动态代理api
     */
    @Test
    public void testInvocation() throws NoSuchMethodException, SecurityException{
        User user = new UserImpl();
        InvocationHandler invocationhandler = new MyInvocationHandler(user);
        //三个参数分别为:类加载器,接口类,请求处理类
        User userproxy=(User)Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), invocationhandler);
        userproxy.talk();

    }
}

运行结果

before method
i am talking
after method

二、Cglib

cglib直接生成二进制码。被代理类不需要实现接口。所创建的动态代理对象继承了被代理类。spring和mybatis框架都用到了cglib。

准备

cglib由github托管
下载jar包
cglib-nodep-3.2.4.jar (含asm.jar)
不推荐下载cglib-3.2.4.jar (不含asm.jar,而asm.jar 为cglib依赖包)

被代理类

package com.test2;
/*
 * cglib 不需要接口
 */
public class UserImpl{
    public void talk() {
        System.out.println("i am talking");
    }
    public void run() {
        System.out.println("i am running");
    }

}

创建方法拦截器类

package com.test2;

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 MyProxy implements MethodInterceptor{
    private Enhancer e = new Enhancer();
    public  Object newInstance(Class<?> clazz){
        //传入被代理类
        e.setSuperclass(clazz);
        //传入方法拦截器
        e.setCallback(this);
        //生成代理类
        return e.create();
    }

    /**
     *  obj : 被代理对象
     *  method : 被代理类的方法对象
     *  args :  被代理类的方法参数对象
     *  proxy : 方法代理对象
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before ----");
        Object result =proxy.invokeSuper(obj, args);
        System.out.println("after ----");
        return result;
    }

}

测试

package com.test2;
import org.junit.Test;

/**
 * <p> Title:MyProxyTest.java</p>
 * <p> Description:cglib 实现动态代理 </p>
 * @author 
 * @date 
 * @version 1.0
 */
public class MyProxyTest {

    @Test
    public void test1(){
        MyProxy proxy = new MyProxy();
        //直接生成代理类 
        UserImpl userproxy=(UserImpl)proxy.newInstance(UserImpl.class);
        userproxy.run();
    }
}

结果

before ----
i am running
after ----
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值