动态代理

静态代理:自己创建代理对象;

动态代理:自动创建代理对象;

生成代理类的字节码文件

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(

proxyName, interfaces, accessFlags)

spring中代理对象生成器

JdkDynamicAopProxy

 

 

动态代理和拦截器都是AOP 思想

 拦截器只要是做校验业务;

动态代理属于代码增强;

代理类工厂:这个类会帮住我们生成一个具体代理类:

public class FactoryProxy implements InvocationHandler {

    private Object abcFactory;

    public FactoryProxy(Object abcFactory) {
        this.abcFactory = abcFactory;
    }

    public void setAbcFactory(Object abcFactory) {
        this.abcFactory = abcFactory;
    }

    public Object getInstance(){
        return  Proxy.newProxyInstance(abcFactory.getClass().getClassLoader(),abcFactory.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("欢迎来到大汗工厂");
//这里需要注意不要将proxy当做目标对象传入,代理类在调用的时候传入的是代理对象本身,比如我们想让代理对象帮我们执行getObject方法,
// public final void getObject(String var1, String var2) throws  {
 //     try {
  //       super.h.invoke(this, m3, new Object[]{var1, var2});
 //     } catch (RuntimeException | Error var4) {
 //        throw var4;
 //     } catch (Throwable var5) {
  //       throw new UndeclaredThrowableException(var5);
  //    }
//   }这个代理类内部的getObject方法
//调用到我们当前方法,当前方法通过反射又去调用上面这个方法,会死循环;

Object invoke
= method.invoke(this.abcFactory, args); System.out.println("欢迎下次光临"); return invoke; } }
public final class proxyTest extends  implements ABCFactory {

   private static Method m1;
   private static Method m3;
   private static Method m2;
   private static Method m0;


   public proxyTest(InvocationHandler var1) throws  {
      super(var1);
   };

   public final boolean equals(Object var1) throws  {
      try {
         return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
      } catch (RuntimeException | Error var3) {
         throw var3;
      } catch (Throwable var4) {
         throw new UndeclaredThrowableException(var4);
      }
   }

   public final void getObject(String var1, String var2) throws  {
      try {
         super.h.invoke(this, m3, new Object[]{var1, var2});
      } catch (RuntimeException | Error var4) {
         throw var4;
      } catch (Throwable var5) {
         throw new UndeclaredThrowableException(var5);
      }
   }

   public final String toString() throws  {
      try {
         return (String)super.h.invoke(this, m2, (Object[])null);
      } catch (RuntimeException | Error var2) {
         throw var2;
      } catch (Throwable var3) {
         throw new UndeclaredThrowableException(var3);
      }
   }

   public final int hashCode() throws  {
      try {
         return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
      } catch (RuntimeException | Error var2) {
         throw var2;
      } catch (Throwable var3) {
         throw new UndeclaredThrowableException(var3);
      }
   }

   static {
      try {
         m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
         m3 = Class.forName("servlet.ABCFactory").getMethod("getObject", new Class[]{Class.forName("java.lang.String"), Class.forName("java.lang.String")});
         m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
         m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      } catch (NoSuchMethodException var2) {
         throw new NoSuchMethodError(var2.getMessage());
      } catch (ClassNotFoundException var3) {
         throw new NoClassDefFoundError(var3.getMessage());
      }
   }
}

以上是程序帮我们生成的代理类;

这个类实现了目标对象的接口和继承Proxy类;

内部重写目标对象接口中的方法;

代理类内部组合了我们定义的FactoryProxy 也就是InvocationHandler

调用这个InvocationHandler的invoca方法 把调用的方法和参数传过去;

真正执行的这个方法的是被代理的类;

代理类中用就静态变量保存接口中定义的方法;

 

spring中@Transactional就是动态代理实现的;

代理类是复用的;

 

由于查看spring中类似Transactional  的注解很多,那么是怎么进行aop 的呢?

我将生成的代理类进行了第二次代理;

public static void main(String[] args) {
        ABCFactory abcFactory = new ABCFactoryImpl();
        FactoryProxy factoryProxy = new FactoryProxy(abcFactory);
        ABCFactory instance = (ABCFactory)factoryProxy.getInstance();
        TowPtoxy towPtoxy = new TowPtoxy(instance);
        ABCFactory  o = (ABCFactory)Proxy.newProxyInstance(instance.getClass().getClassLoader(), instance.getClass().getInterfaces(), towPtoxy);
        FileOutputStream fileOutputStream = null;
        o.getObject("123456","韩");
        try {
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                    "proxyTest", instance.
                            getClass().getInterfaces());
            File file = new File("D://proxy.class");
            fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(proxyClassFile);
        }catch (Exception e){
            System.out.println("出现异常");
        }finally {
            try {
                if(fileOutputStream!=null){
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
            }catch (Exception e){

            }


        }

    }
public class TowPtoxy implements InvocationHandler {
    private Object object;

    public TowPtoxy(Object object) {
        this.object=object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("第二次加强");
        Object invoke = method.invoke(object, args);
        System.out.println("第二次加强结束");
        return invoke;
    }
}

代理后输出如下

第二次加强
欢迎来到大汗工厂
生产商品:123456:韩
欢迎下次光临
第二次加强结束

 

成功了

代理类没有变化;

 

spring的实现 :

代理类:JdkDynamicAopProxy(类似我们的FactoryProxy)
MethodInvocation方法调用;关键方法proceed()

proceed方法中 遍历拦截器
所有拦截器接口
调用MethodInterceptor的
invoke()
方法同时将MethodInvocation传入进去 类似于上下文信息;
invoke()中执行增强前置方法比如开启事务 之后调用
MethodInvocation的proceedWithInvocation()

最后在finally中执行后置增强;比如提交回滚





 

posted @ 2020-08-03 20:39  不知无畏  阅读(138)  评论(0)    收藏  举报