• 一、spring的成长之路——代理设计模式


    java常用的设计模式详解:

    1.代理模式(JDK的动态代理)

    【IDept.java】

    ​ 这是一个简单的就接口,进行数据的更新

    package com.itcloud.pattern.proxy;
    
    public interface IDept {
    	void update();
    }
    

    【DeptImp.java】

    ​ Dept的实现类

    package com.itcloud.pattern.proxy;
    
    public class DeptImpl implements IDept {
    	@Override
    	public void update() {
    		System.out.println("完成核心功能,进行数据的更新操作");
    	}
    }
    

    【InvoProxy.java】

    ​ 代理类,被代理对象只需要完成核心功能,而其他的功能都由代理对象完成

    package com.itcloud.pattern.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class InvoProxy implements InvocationHandler {
    
    	private Object obj;
    
    	// 首先要获取代理对象
    
    	public Object getProxyInterface(Object obj) {
    		this.obj = obj;
    		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    	}
    
    	/**
    	  实现的基本步骤
    	  1.获取代理类对象,然后获取其接口
    	  2.生成新的类,实现代理类的接口,这个类其实只是字节码文件
    	  3.在新生成的类中进行代码的执行
    	 */
    	
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		System.out.println("数据库开启事物");// 这些事情由代理类完成		
    		try {
    			return method.invoke(this.obj, args); // 代理类完成核心功能
    		} catch (Exception e) {
    
    		} finally {
    			System.out.println("进行事物的回滚操作");
    		}
    		return null;
    	}
    }
    

    【TestDemo.java】

    public class TestDemo {
    	public static void main(String[] args) {
    		IDept dept = (IDept)new InvoProxy().getProxyInterface(new DeptImpl());
    		dept.update();
    	}
    }
    //测试结果
    /*
        数据库开启事物
        完成核心功能,进行数据的更新操作
        进行事物的回滚操作
    */
    

    在代码中我们说过,代理对象会生成一个代理类,那么我们来看一下这个类究竟长什么样

    首先在测试类中将字节码写入本地文件

    【TestDemo.java】

    import sun.misc.ProxyGenerator;
    
    import java.io.FileOutputStream;
    
    public class TestDemo {
    	public static void main(String[] args) throws Exception {
    		IDept dept = (IDept)new InvoProxy().getProxyInterface(new DeptImpl());
    		dept.update();
    		byte[] $Proxy0 = ProxyGenerator.generateProxyClass("$Proxy0", new Class<?>[]{IDept.class});
    		FileOutputStream out = new FileOutputStream("G:\$Proxy0.class");
    		out.write($Proxy0);
    		out.close();
    	}
    }
    

    我们可以在g盘中生成一个$Proxy0.class文件,这个文件就是类的字节码文件,你看不懂我也看不懂这时候需要借用反编译软件(jd-gui-0.3.6),进行反编译

    【$Proxy0.class】

    import com.itcloud.pattern.proxy.IDept;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    public final class $Proxy0
      extends Proxy
      implements IDept
    {
      private static Method m1;
      private static Method m2;
      private static Method m0;
      private static Method m3;
      
      public $Proxy0(InvocationHandler paramInvocationHandler)
        throws 
      {
        super(paramInvocationHandler);
      }
      
      public final boolean equals(Object paramObject)
        throws 
      {
        try
        {
          return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final String toString()
        throws 
      {
        try
        {
          return (String)this.h.invoke(this, m2, null);
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final int hashCode()
        throws 
      {
        try
        {
          return ((Integer)this.h.invoke(this, m0, null)).intValue();
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final Boolean update()
        throws 
      {
        try
        {
          return (Boolean)this.h.invoke(this, m3, null);
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      static
      {
        try
        {
          m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
          m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
          m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
          m3 = Class.forName("com.itcloud.pattern.proxy.IDept").getMethod("update", new Class[0]);
          return;
        }
        catch (NoSuchMethodException localNoSuchMethodException)
        {
          throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException localClassNotFoundException)
        {
          throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
        }
      }
    }
    

    总结:jdk动态代理必须要有接口

    3.cglib代理

    cglib中,被代理对象不需要继承相关接口

    【pom.xml】文件中添加依赖

    <dependency>
    	<groupId>cglib</groupId>
    	<artifactId>cglib</artifactId>
    	<version>3.2.4</version>
    </dependency>
    

    【Student.java】

    package com.itcloud.pattern.cglib;
    public class Student {
    
        public void update() {
            System.out.println("进行数据的更新操作");
        }
    }
    

    【CglibProxy.java】

    package com.itcloud.pattern.cglib;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class CglibProxy implements MethodInterceptor {
    
        //获取代理类的对象
        public Object getInstance(Class<?> clazz) {
            Enhancer enhancer = new Enhancer();
            enhancer.setCallback(this);
            enhancer.setSuperclass(clazz);//设置生成代理类的父类
            //enhancer.create()这个方法会创建com.itcloud.pattern.cglib.Student$$EnhancerByCGLIB$$4c126679@20e2cbe0代理类,这个代理类是被代理类的子类
            return enhancer.create();//enhancer.create() instanceof Student 返回结果true
        }
    
    
        /**
         *
         * @param obj cglib生成的代理类
         * @param method 被代理对象中的方法
         * @param args 方法的参数
         * @param methodProxy 代理方法,即生成代理类中的方法
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("数据更新前,事物开启");
    
            try {
                return methodProxy.invokeSuper(obj, args);//明确调用父类中的方法
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                System.out.println("出现异常,事物回滚,rollback");
            }
            return null;
        }
    }
    

    此时我们也可以像JDK动态代理那样对生成的代理类进行字节码反编译。
    爱生活爱分享欢迎您的关注与加入自学交流群:461265466这里写图片描述

  • 相关阅读:
    拆分跨天的时间数据
    模板
    更换数据库服务器迁移步骤
    缺失索引
    flex布局解说和属性
    Vuejs中关于computed、methods、watch,mounted的区别
    皮囊
    回家
    江苏旅游计划
    重写原生alert,弹出层过一会就消失
  • 原文地址:https://www.cnblogs.com/hu1056043921/p/8878213.html
Copyright © 2020-2023  润新知