Java实现动态代理

来源:互联网 发布:广东省网络问政 编辑:程序博客网 时间:2024/06/08 09:38

1 前言

Java动态代理机制使用十分广泛,如AOP的实现、Mybatis框架的实现,Java动态代理实现有两种方式:JDK动态代理和Cglib动态代理,下面就举例说明该如何使用。

2 JDK动态代理

2.1 实现说明

JDK动态代理生成代理对象,不需要借助第三方Jar,利用jar反射实现,目标对象必须实现接口

2.2 创建接口和实现类

接口如下:

package com.pengmm.service;public interface UserService {    public String getUserName(String name);    public int getUserAge(int age);}

接口实现类如下:

package com.pengmm.service;public class UserServiceImpl implements UserService {    @Override    public String getUserName(String name) {        System.out.println("name="+name);        return name;    }    @Override    public int getUserAge(int age) {        System.out.println("age="+age);        return age;    }}

2.3 实现InvocationHandler接口并生成代理对象

具体代码如下:

package com.pengmm.util;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * JDK动态代理生成代理对象,不需要借助第三方Jar,利用jar反射实现 * 目标对象必须实现接口 * @author pengmm */public class JdkProxy implements InvocationHandler {    // 目标对象    private Object target;    /**     * 构造函数     * @param target 目标对象     */    public JdkProxy(Object target) {        this.target = target;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        // 前置方法        System.out.println(proxy.getClass().getName()+"==========代理的前置方法===============");        Object result = method.invoke(target, args);        System.out.println(target.getClass().getName()+"==========代理的后置方法===============");        return result;    }    /**     * 生成代理对象     * @return     */    public Object getProxy() {        ClassLoader classLoader = target.getClass().getClassLoader();        Class<?>[] interfaces = target.getClass().getInterfaces();        Object newProxyInstance =                 Proxy.newProxyInstance(classLoader, interfaces, this);        return newProxyInstance;    }}

2.4 测试调用

具体测试代码如下:

package test.com.pengmm.mapper;import com.pengmm.service.UserService;import com.pengmm.service.UserServiceImpl;import com.pengmm.util.JdkProxy;public class JdkTest {    public static void main(String[] args) {        // 创建目标对象        UserService userService = new UserServiceImpl();        // 生成并获取代理对象        JdkProxy jdkProxy = new JdkProxy(userService);        UserService proxy = (UserService) jdkProxy.getProxy();        // 代理对象调用方法        proxy.getUserName("张三");        proxy.getUserAge(18);    }}

控制台结果如下:

com.sun.proxy.$Proxy0==========代理的前置方法===============name=张三com.pengmm.service.UserServiceImpl==========代理的后置方法===============com.sun.proxy.$Proxy0==========代理的前置方法===============age=18com.pengmm.service.UserServiceImpl==========代理的后置方法===============

3 Cglib动态代理

3.1 说明

通过Cglib方式生成代理类,依赖jar包:asm-5.1.jar、cglib-3.2.4.jar,原理:根据目标类的字节码文件生成子类并拦截目标类的所有可继承方法,从而动态代理;
优势:可以代理具体类,不需要实现接口

3.2 创建并生成代理类

具体代码如下:

package com.pengmm.util;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;/** * 通过Cglib方式生成代理类,依赖jar包:asm-5.1.jar、cglib-3.2.4.jar * 原理:根据目标类的字节码文件生成子类并拦截目标类的所有可继承方法,从而动态代理 * 优势:可以代理具体类,不需要实现接口 * @author pengmm * */public class CglibProxy implements MethodInterceptor {    // 增强类,用于创建子类,即代理类    private Enhancer enhancer;      /**     * 构造函数     * @param target 目标类的Class对象,即字节码     */    public CglibProxy(Object target) {        this.enhancer = new Enhancer();          enhancer.setSuperclass((Class<?>)target);          enhancer.setCallback(this);     }    /**     * 对目标类的可继承方法进行拦截     */    @Override    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {        System.out.println("==========代理的前置方法===============");        // 调用目标对象的方法        Object result = methodProxy.invokeSuper(o, args);        System.out.println("==========代理的后置方法===============");        return result;    }    /**     * 生成的代理对象     * @return     */    public Object getProxy() {        Object proxy = enhancer.create();          return proxy;    }}

3.3 测试调用

具体代码如下:

package test.com.pengmm.mapper;import com.pengmm.service.UserServiceImpl;import com.pengmm.util.CglibProxy;public class CglibTest {    public static void main(String[] args) {        CglibProxy cglibProxy = new CglibProxy(UserServiceImpl.class);          UserServiceImpl proxy = (UserServiceImpl) cglibProxy.getProxy();        proxy.getUserName("张三");        proxy.getUserAge(18);    }}

控制台输出结果如下:

==========代理的前置方法===============name=张三==========代理的后置方法=========================代理的前置方法===============age=18==========代理的后置方法===============
0 0
原创粉丝点击