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=18
com.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
==========代理的后置方法===============