您的位置:首页 > 编程语言 > Java开发

动态代理-JDK和Cglib实现

2016-11-30 21:42 302 查看

动态代理

一、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 ----
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态代理 JDK cglib
相关文章推荐