java动态代理实现的两种方式详解编程语言
两种动态代理:
一.jdk动态代理,jdk动态代理是由Java内部的反射机制来实现的,目标类基于统一的接口(InvocationHandler)
二.cglib动态代理,cglib动态代理底层则是借助asm来实现的,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
主要应用的框架:
Spring中的AOP,Struts2中的拦截器
程序代码如下:
1、定义接口和实现类
public interface UserService {
public String getName(int id);
public Integer getAge(int id);
}
import com.example.service.UserService;
public class UserServiceImpl implements UserService {
public String getName(int id) {
System.out.println( getName );
return cat
}
public Integer getAge(int id) {
System.out.println( getAge );
return 10;
}
}
2、jdk动态代理实现
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
/**
* 绑定委托对象并返回一个代理类
*
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( getName .equals(method.getName())) {
System.out.println( before + method.getName() + );
Object result = method.invoke(target, args);
System.out.println( after + method.getName() + );
return result;
} else {
Object result = method.invoke(target, args);
return result;
}
}
}
import com.example.service.UserService;
import com.example.service.impl.UserServiceImpl;
/**
* 测试类
*/
public class RunJDK {
public static void main(String[] args) {
MyInvocationHandler proxy = new MyInvocationHandler();
UserService userServiceProxy = (UserService) proxy.bind(new UserServiceImpl());
System.out.println(userServiceProxy.getName(1));
System.out.println(userServiceProxy.getAge(1));
}
}
运行结果:
before getName
getName
after getName
cat
getAge
3、cglib动态代理实现:
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
CGLIB的核心类:
net.sf.cglib.proxy.Enhancer – 主要的增强类
net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用。
net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;
第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.Method对象的一般反射调用,或者使用 net.sf.cglib.proxy.MethodProxy对象调用。net.sf.cglib.proxy.MethodProxy通常被首选使用,因为它更快。
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGLIBProxy implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println( ++++++before + methodProxy.getSuperName() + ++++++ );
System.out.println(method.getName());
Object result = methodProxy.invokeSuper(o, objects);
System.out.println( ++++++after + methodProxy.getSuperName() + ++++++ );
return result;
}
}
import com.example.service.UserService;
import com.example.service.impl.UserServiceImpl;
/**
* 测试CGLIB
*/
public class RunCGLIB {
public static void main(String[] args) {
CGLIBProxy cglibProxy = new CGLIBProxy();
UserService userService = (UserService) cglibProxy.getInstance(new UserServiceImpl());
userService.getName(1);
userService.getAge(1);
}
}
运行结果:
++++++before CGLIBgetName0++++++
getName
getName
++++++after CGLIBgetName0++++++
++++++before CGLIBgetAge1++++++
getAge
getAge
++++++after CGLIBgetAge1++++++
转载请注明来源网站:blog.ytso.com谢谢!
14668.html
cjava相关文章
- java判断一个对象是否为空_Java中判断对象是否为空的方法的详解
- 我的世界java版需要多少钱_我的世界Java版20w49a快照版[通俗易懂]
- java集合类面试题_Java集合类相关面试题
- java工作流_Java 实现简单工作流
- MySQL字段类型如何转为java_Java JDBC中,MySQL字段类型到JAVA类型的转换
- java的动态代理底层解析
- java list 转json 字符串_JSON的String字符串与Java的List列表对象的相互转换
- 【Android 安全】DEX 加密 ( Java 工具开发 | 加密解密算法 API | 编译代理 Application 依赖库 | 解压依赖库 aar 文件 )
- Java的运行时数据区域
- 从java到JavaScript(2):对比Java/Go/Swift/Rust看Dart
- java JNI: C 语言调用 Java 方法示例详解编程语言
- Java获得代理环境下的真实IP详解编程语言
- java.lang.String (JDK1.8)详解编程语言
- Java学习笔记之九java二维数组及其多维数组的内存应用拓展延伸详解编程语言
- java学习笔记14–动态代理详解编程语言
- java 标准输出与标准错误 out与 err 区别 用法 联系 java中的out与err区别 System.out和System.err的区别 System.out.println和System.err.println的区别 Java重定向System.out和System.err详解编程语言
- Java动态代理一——动态类Proxy的使用详解编程语言
- 详解 Java 中的三种代理模式编程语言
- Java问题-java进程占用内存过高,排查原因详解编程语言
- 自己写一个java.lang.reflect.Proxy代理的实现详解编程语言
- 使用Java操作MySQL数据库快速精准查询(java查询mysql数据库)
- 数据如何使用Java连接MySQL修改数据(javamysql修改)
- 机制解析Redis Java过期机制(redisjava过期)
- Linux平台上C语言接口调用Java语言实现(linux c调java)
- MSSQL与Java的数据库连接实践(mssql连接java)
- Java与Oracle 一种天生的结合(java属于oracle)
- 本使用Oracle Java 进行升级新版本带来新体验(oracle java版)