java 中动态代理的实现
这里有新鲜出炉的 Java 并发编程示例, 程序狗速度看过来!
Java 程序设计语言
java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言, 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台 (即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se)) 的总称
本篇文章主要介绍了 Java 中两种动态代理的实现: jdk 动态代理; cglib 动态代理具有一定的参考价值, 下面跟着小编一起来看下吧
动态代理的实现
使用的模式: 代理模式
代理模式的作用是: 为其他对象提供一种代理以控制对这个对象的访问类似租房的中介
两种动态代理:
(1)jdk 动态代理, jdk 动态代理是由 Java 内部的反射机制来实现的, 目标类基于统一的接口(InvocationHandler)
(2)cglib 动态代理, cglib 动态代理底层则是借助 asm 来实现的, cglib 这种第三方类库实现的动态代理应用更加广泛, 且在效率上更有优势
主要应用的框架:
Spring 中的 AOP,Struts2 中的拦截器
具体实现:
1 定义接口和实现类
- package com.example.service;
- public interface UserService {
- public String getName(int id);
- public Integer getAge(int id);
- }
- package com.example.service.impl;
- 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;
- }
- }
2jdk 动态代理实现
- package com.example.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;
- }
- }
- }
- package com.example.jdk;
- 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------
- 10
3cglib 动态代理实现:
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 通常被首选使用, 因为它更快
- package com.example.cglib;
- 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;
- }
- }
- package com.example.cglib;
- 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 CGLIB$getName$0++++++
- getName
- ------getName------
- ++++++after CGLIB$getName$0++++++
- ++++++before CGLIB$getAge$1++++++
- getAge
- ------getAge------
- ++++++after CGLIB$getAge$1++++++
以上就是本文的全部内容, 希望本文的内容对大家的学习或者工作能带来一定的帮助, 同时也希望多多支持 PHPERZ!
来源: http://www.phperz.com/article/18/0205/358957.html