• java的动态代理如何实现


    一. JdkProxy

    jdkproxy动态代理必须基于接口(interface)实现

    1. 接口UserInterface.java
    1. public interface UserService {
    2. String getUserName(String userCde);
    3. }
    1. 原始实现类:UseServiceImpl.java
    1. public class UserServiceImpl implements UserSerice {
    2. @Override
    3. public String getUserName(String userCde) {
    4. System.out.println("the name of " + userCde + "is Austin");
    5. return "Austin";
    6. }
    7. }
    1. 代理类 :UserProxyFactoryBJdk.java
    1. public class UserProxyFactoryBJdk {
    2. public static UserService getUserServiceProxy(UserService origin) {
    3. UserService userService = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader()
    4. , new Class[]{UserService.class}
    5. , new InvocationHandler() { //动态代理实现类
    6. @Override
    7. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    8. System.out.println("before");
    9. Object o = method.invoke(origin, args);
    10. System.out.println("after");
    11. return o;
    12. }
    13. });
    14. return userService;
    15. }
    16. public static void main(String[] args) {
    17. UserService userService = getUserServiceProxy(new UserServiceImpl());
    18. userService.getUserName("123");
    19. }
    20. }

    执行结果:
    before
    the name of 123is Austin
    after

    二. Cglib动态代理

    Cglib实现动态代理与JdkProxy不同, 是通过构建继承类实现

    1. 原始类UseServiceImpl.java
    1. public class UserServiceImpl implements UserSerice {
    2. @Override
    3. public String getUserName(String userCde) {
    4. System.out.println("the name of " + userCde + "is Austin");
    5. return "Austin";
    6. }
    7. }
    1. 代理类 :UserProxyFactoryByCglib.java
    1. public static UserServiceImpl getUserServiceProxy(UserService origin) {
    2. Enhancer enhancer = new Enhancer();
    3. // 设置debug信息
    4. System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY
    5. , "/home/aa/dev/testfile/com/austin/meta/cxf/");
    6. // 设置父类:UserServiceImpl
    7. enhancer.setSuperclass(UserServiceImpl.class);
    8. //设置代理实现逻辑
    9. enhancer.setCallback(new CglibInterCeptor() {
    10. public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    11. System.out.println("CglibInterCeptor.intercept-before");
    12. Object o = proxy.invokeSuper(obj, args);
    13. System.out.println("CglibInterCeptor.intercept-after");
    14. return o;
    15. }
    16. });
    17. UserServiceImpl userService = ((UserServiceImpl) enhancer.create());
    18. return userService;
    19. }
    20. public static void main(String[] args) {
    21. UserService userService = getUserServiceProxy(new UserServiceImpl());
    22. userService.getUserName("123");
    23. }

    1. 执行结果
      CglibInterCeptor.intercept-before
      the name of 123is Austin
      CglibInterCeptor.intercept-after

    三. Java动态编译

    通过JavaCompiler动态编译java源文件,并将相应字节码加载到JVM中,其编译底层通过javac -d 命令进行编译

    1. 需要动态编译的类文件
    1. package com.austin.meta.dynamiccompiler;
    2. public class UserServiceImplE extends UserServiceImpl {
    3. public UserServiceImplE() {
    4. }
    5. public String getUserName(String userCde) {
    6. System.out.println("before");
    7. super.getUserName(userCde);
    8. System.out.println("after");
    9. return "Austin";
    10. }
    11. }
    1. 动态编译类
    1. public class JavaCompilerTest {
    2. private static String basePath = "";
    3. public static void main(String[] args) throws Exception{
    4. System.out.println(ClassLoader.getSystemResource(""));
    5. Class<?> userServiceImplE = compiler("UserServiceImplE");
    6. UserServiceImpl o = (UserServiceImpl)userServiceImplE.getConstructor(null).newInstance(null);
    7. o.getUserName("235");
    8. }
    9. private static Class<?> getClass(String pakcge, String className) {
    10. Class<?> clazz = null;
    11. try {
    12. clazz = Class.forName(pakcge + "." +className, true, JavaCompilerTest.class.getClassLoader());
    13. } catch (ClassNotFoundException e) {
    14. e.printStackTrace();
    15. }
    16. return clazz;
    17. }
    18. /**
    19. * 动态编译java类,并通加载到JVM
    20. */
    21. private static Class<?> compiler(String className) throws IOException {
    22. File javaSrcFile = new File(basePath+ "/" + className + ".java");
    23. JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    24. StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);
    25. List<String> options = Arrays.asList("-d", ClassLoader.getSystemResource("").toString());
    26. JavaCompiler.CompilationTask task = compiler.getTask(null
    27. , standardFileManager, null, options, null, standardFileManager.getJavaFileObjects(javaSrcFile));
    28. Boolean isCompilerSuccess = task.call();
    29. if(!isCompilerSuccess) {
    30. return null;
    31. }
    32. Class<?> clazz = getClass("com.austin.meta.dynamiccompiler", className);
    33. return clazz;
    34. }
    35. }

    1. 执行结果
      before
      the name of 235is Austin
      after

  • 相关阅读:
    Win11系统鼠标右键无法打开一直转圈解决方法
    【MySQL】数据类型
    关于nginx升级--存在0day漏洞
    ECharts数据可视化项目【6】
    python bytes 方法
    关于黑马hive课程案例FineBI中文乱码的解决
    4.求1000以内的所有完数
    OpenCV16-图像连通域分析
    linux上gitlab备份与还原
    labview中6种机械动作的区别
  • 原文地址:https://blog.csdn.net/Lzfnemo2009/article/details/132794597