当前位置: 首页 > 编程笔记 >

java中动态代理的实现

澹台正真
2023-03-14
本文向大家介绍java中动态代理的实现,包括了java中动态代理的实现的使用技巧和注意事项,需要的朋友参考一下

动态代理的实现

使用的模式:代理模式。

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。类似租房的中介。

两种动态代理:

(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;
  }
}

2、jdk动态代理实现

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

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通常被首选使用,因为它更快。

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++++++

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持小牛知识库!

 类似资料:
  • 本文向大家介绍Java动态代理静态代理实例分析,包括了Java动态代理静态代理实例分析的使用技巧和注意事项,需要的朋友参考一下 代理模式:为其他对象提供一种代理以控制某个对象的访问。用在:在某些情况下,一个客户不想或者不能直接访问另一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用,代理对象还可以完成它附加的操作。 例子:就像房东、租客、中介的关系。中介(代理对象)为房东(真实对象)出租

  • 本文向大家介绍浅谈Java代理(jdk静态代理、动态代理和cglib动态代理),包括了浅谈Java代理(jdk静态代理、动态代理和cglib动态代理)的使用技巧和注意事项,需要的朋友参考一下 一、代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强。加入一些非业务性代码,比如事务、日志、报警发邮件等操作。 二、jdk静态代理 1、业务接口 2、业务实现类 3、代理类

  • 本文向大家介绍详解Java动态代理的实现机制,包括了详解Java动态代理的实现机制的使用技巧和注意事项,需要的朋友参考一下 一、概述   代理是一种设计模式,其目的是为其他对象提供一个代理以控制对某个对象的访问,代理类负责为委托类预处理消息,过滤消息并转发消息以及进行消息被委托类执行后的后续处理。为了保持行为的一致性,代理类和委托类通常会实现相同的接口。   按照代理的创建时期,代理类可分为两种:

  • 本文向大家介绍Java中的引用和动态代理的实现详解,包括了Java中的引用和动态代理的实现详解的使用技巧和注意事项,需要的朋友参考一下 我们知道,动态代理(这里指JDK的动态代理)与静态代理的区别在于,其真实的代理类是动态生成的。但具体是怎么生成,生成的代理类包含了哪些内容,以什么形式存在,它为什么一定要以接口为基础? 如果去看动态代理的源代码(java.lang.reflect.Proxy),会

  • 本文向大家介绍Java两种方式实现动态代理,包括了Java两种方式实现动态代理的使用技巧和注意事项,需要的朋友参考一下 一、JDK动态代理 Java 在 java.lang.reflect 包中有自己的代理支持,该类(Proxy.java)用于动态生成代理类,只需传入目标接口、目标接口的类加载器以及 InvocationHandler 便可为目标接口生成代理类及代理对象。我们称这个Java技术为:

  • 本文向大家介绍java实现动态代理方法浅析,包括了java实现动态代理方法浅析的使用技巧和注意事项,需要的朋友参考一下 一些Java项目中在mybatis与spring整合中有MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类。 有鉴于此,本文浅析了java的动态代理。 本文使用动态代理模拟处理事务的拦截器。 接口: 实现类: java动态代理的实现