代理模式

参考资料

图解设计模式

大话设计模式

设计模式之禅

github我见过最好的设计模式

http://c.biancheng.net/view/1...

定义

  • 代理模式为其余对象提供一种代理,用来管制对于这个对象的拜访
  • 在客户类和指标类之间起到中介作用
  • 结构型设计模式

类图

生存中的代理模式

  • 房产中介
  • 快递小哥
  • 黄牛党

应用场景

  • 爱护指标对象
  • 加强指标对象的性能

案例

动态代理

显示申明被代理的对象

public class ZhangLaosan implements IPerson {  private IPerson zhangsan;  public ZhangLaosan(IPerson person) {    this.zhangsan = person;  }  public void findLove() {    System.out.println("张老三开始物色");    person.findLove();    System.out.println("开始来往");  }}

编译期就分明了

有点相似于装璜者模式

动静代理

JDK

  • Proxy#newProxyInstance
  • InvocationHandler

public class JdkMeipo implements InvocationHandler {  private IPerson target;  public IPerson getInstance(IPerson target){    this.target = target;    Class<?> clazz =  target.getClass();    return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);  }  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    before();    Object result = method.invoke(this.target,args);    after();    return result;  }  private void after() {    System.out.println("双方同意,开始来往");  }  private void before() {    System.out.println("我是媒婆,曾经收集到你的需要,开始物色");  }}

问题

如同动静代理和动态代理没有区别

  • 动静代理编译期确认的,没有硬编码

cglibProxy

导入依赖
<dependency>  <groupId>cglib</groupId>  <artifactId>cglib-nodep</artifactId>  <version>2.2</version></dependency>
  • 实现net.sf.cglib.proxy.MethodInterceptor
public class CGlibMeipo implements MethodInterceptor {  public Object getInstance(Class<?> clazz) throws Exception{    //相当于Proxy,代理的工具类    Enhancer enhancer = new Enhancer();    enhancer.setSuperclass(clazz);    enhancer.setCallback(this);    return enhancer.create();  }  public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {    before();    Object obj = methodProxy.invokeSuper(o,objects);    after();    return obj;  }  private void before(){    System.out.println("我是媒婆,我要给你找对象,当初曾经确认你的需要");    System.out.println("开始物色");  }  private void after(){    System.out.println("OK的话,筹备办事");  }}
个别$结尾的类都是动静代理的类

深刻理解代理模式

JDK的动静代理

通过反编译来查看字节码文件

    public static void generator() {        byte[] bytes = ProxyGenerator.generateProxyClass("$proxy0", new Class[]{IPerson.class});        FileOutputStream os = null;        try {            os = new FileOutputStream("/Users/zzy/Downloads/$proxy0.class");            os.write(bytes);            os.close();            System.out.println("print success");        } catch (Exception e) {            e.printStackTrace();        } finally {            if (os != null) {                try {                    os.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }

反编译对应文件

jad $Proxy0.class

jad装置步骤能够参考https://blog.csdn.net/qing_ge...

也能够间接放到idea中查看

编译后的内容如下

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//import com.zzjson.pattern.proxy.dynamicproxy.jdkproxy.IPerson;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 IPerson {  private static Method m1;  private static Method m4;  private static Method m2;  private static Method m3;  private static Method m0;  public $proxy0(InvocationHandler var1) throws  {    super(var1);  }  public final boolean equals(Object var1) throws  {    try {      return (Boolean)super.h.invoke(this, m1, new Object[]{var1});    } catch (RuntimeException | Error var3) {      throw var3;    } catch (Throwable var4) {      throw new UndeclaredThrowableException(var4);    }  }  public final void findLove() throws  {    try {      super.h.invoke(this, m4, (Object[])null);    } catch (RuntimeException | Error var2) {      throw var2;    } catch (Throwable var3) {      throw new UndeclaredThrowableException(var3);    }  }  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 void buyInsure() throws  {    try {      super.h.invoke(this, m3, (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);    } catch (RuntimeException | Error var2) {      throw var2;    } catch (Throwable var3) {      throw new UndeclaredThrowableException(var3);    }  }  static {    try {      m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));      m4 = Class.forName(" com.zzjson.pattern.proxy.dynamicproxy.jdkproxy.IPerson").getMethod("findLove");      m2 = Class.forName("java.lang.Object").getMethod("toString");      m3 = Class.forName(" com.zzjson.pattern.proxy.dynamicproxy.jdkproxy.IPerson").getMethod("buyInsure");      m0 = Class.forName("java.lang.Object").getMethod("hashCode");    } catch (NoSuchMethodException var2) {      throw new NoSuchMethodError(var2.getMessage());    } catch (ClassNotFoundException var3) {      throw new NoClassDefFoundError(var3.getMessage());    }  }}

要害代码

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

h实际上就是代理对象

所以说实际上就是调用的

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  before();  Object result = method.invoke(this.target,args);  after();  return result;}

手写

  1. 动静生成源码.java文件

    1. 本人手动拼代码
  2. Java文件输入到磁盘,保留为文件$Proxy0.java

    String filePath = MyProxy.class.getResource("").getPath();//           System.out.println(filePath);File f = new File(filePath + "$Proxy0.java");FileWriter fw = new FileWriter(f);fw.write(src);fw.flush();fw.close();
  3. 把.java文件编译成$proxy0.class文件

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager manage = compiler.getStandardFileManager(null,null,null);Iterable iterable = manage.getJavaFileObjects(f);JavaCompiler.CompilationTask task = compiler.getTask(null,manage,null,null,null,iterable);task.call();manage.close();
  4. 把生成的.class文件加载到JVM中

    Class proxyClass =  classLoader.findClass("$Proxy0");Constructor c = proxyClass.getConstructor(MyInvocationHandler.class);f.delete();
  5. 返回新的代理对象

     return c.newInstance(h);
本人的类加载器
public class MyClassLoader extends ClassLoader {  private File classPathFile;  public MyClassLoader(){    String classPath = MyClassLoader.class.getResource("").getPath();    this.classPathFile = new File(classPath);  }  @Override  protected Class<?> findClass(String name) throws ClassNotFoundException {    String className = MyClassLoader.class.getPackage().getName() + "." + name;    if(classPathFile  != null){      File classFile = new File(classPathFile,name.replaceAll("\\.","/") + ".class");      if(classFile.exists()){        FileInputStream in = null;        ByteArrayOutputStream out = null;        try{          in = new FileInputStream(classFile);          out = new ByteArrayOutputStream();          byte [] buff = new byte[1024];          int len;          while ((len = in.read(buff)) != -1){            out.write(buff,0,len);          }          return defineClass(className,out.toByteArray(),0,out.size());        }catch (Exception e){          e.printStackTrace();        }      }    }    return null;  }}

CGLIb和DJK的区别

  • CGLIB采纳继承的形式,重写父类的办法
  • JDK采纳的形式,要求代理的指标对象肯定要实现一个接口
思维:都是通过生成字节码,重组成一个新的类
  • JDK Proxy对于用户而言,依赖性更强,调用也更加平安
  • CGLIB要求指标类不能有final的办法,final办法不能被代理
  • CGLIB更快

    • 效率更高,性能也更高,底层没有用到反射
  • JDK的生成逻辑较为简单,执行效率姚笛,每次都要用反射

常见的动静代理

Spring

AOP

BeanPostProcessor外围还是在对象后置处理器

AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization`

org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization

public Object postProcessAfterInitialization(Object bean, String beanName) {  if (this.advisor == null || bean instanceof AopInfrastructureBean) {    // Ignore AOP infrastructure such as scoped proxies.    return bean;  }  if (bean instanceof Advised) {    Advised advised = (Advised) bean;    if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {      // Add our local Advisor to the existing proxy's Advisor chain...      if (this.beforeExistingAdvisors) {        advised.addAdvisor(0, this.advisor);      }      else {        advised.addAdvisor(this.advisor);      }      return bean;    }  }  if (isEligible(bean, beanName)) {    ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);    if (!proxyFactory.isProxyTargetClass()) {      evaluateProxyInterfaces(bean.getClass(), proxyFactory);    }    proxyFactory.addAdvisor(this.advisor);    customizeProxyFactory(proxyFactory);    return proxyFactory.getProxy(getProxyClassLoader());  }  // No proxy needed.  return bean;}

最终会执行到

DefaultAopProxyFactory#createAopProxy

org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {            Class<?> targetClass = config.getTargetClass();            if (targetClass == null) {                throw new AopConfigException("TargetSource cannot determine target class: " +                        "Either an interface or a target is required for proxy creation.");            }            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {                return new JdkDynamicAopProxy(config);            }            return new ObjenesisCglibAopProxy(config);        }        else {            return new JdkDynamicAopProxy(config);        }    }
JDK动静代理
public Object getProxy(@Nullable ClassLoader classLoader) {  if (logger.isTraceEnabled()) {    logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());  }  Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);  findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}
对应的InvocationHandler

org.springframework.aop.framework.JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  Object oldProxy = null;  boolean setProxyContext = false;  TargetSource targetSource = this.advised.targetSource;  Object target = null;  try {    if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {      // The target does not implement the equals(Object) method itself.      return equals(args[0]);    }    else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {      // The target does not implement the hashCode() method itself.      return hashCode();    }    else if (method.getDeclaringClass() == DecoratingProxy.class) {      // There is only getDecoratedClass() declared -> dispatch to proxy config.      return AopProxyUtils.ultimateTargetClass(this.advised);    }    else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&             method.getDeclaringClass().isAssignableFrom(Advised.class)) {      // Service invocations on ProxyConfig with the proxy config...      return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);    }    Object retVal;    if (this.advised.exposeProxy) {      // Make invocation available if necessary.      oldProxy = AopContext.setCurrentProxy(proxy);      setProxyContext = true;    }    // Get as late as possible to minimize the time we "own" the target,    // in case it comes from a pool.    target = targetSource.getTarget();    Class<?> targetClass = (target != null ? target.getClass() : null);    // Get the interception chain for this method.    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);    // Check whether we have any advice. If we don't, we can fallback on direct    // reflective invocation of the target, and avoid creating a MethodInvocation.    if (chain.isEmpty()) {      // We can skip creating a MethodInvocation: just invoke the target directly      // Note that the final invoker must be an InvokerInterceptor so we know it does      // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.      Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);      retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);    }    else {      // We need to create a method invocation...      MethodInvocation invocation =        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);      // Proceed to the joinpoint through the interceptor chain.      retVal = invocation.proceed();    }    // Massage return value if necessary.    Class<?> returnType = method.getReturnType();    if (retVal != null && retVal == target &&        returnType != Object.class && returnType.isInstance(proxy) &&        !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {      // Special case: it returned "this" and the return type of the method      // is type-compatible. Note that we can't help if the target sets      // a reference to itself in another returned object.      retVal = proxy;    }    else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {      throw new AopInvocationException(        "Null return value from advice does not match primitive return type for: " + method);    }    return retVal;  }  finally {    if (target != null && !targetSource.isStatic()) {      // Must have come from TargetSource.      targetSource.releaseTarget(target);    }    if (setProxyContext) {      // Restore old proxy.      AopContext.setCurrentProxy(oldProxy);    }  }}
CGLIB动静代理
public Object getProxy(@Nullable ClassLoader classLoader) {  if (logger.isTraceEnabled()) {    logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());  }  try {    Class<?> rootClass = this.advised.getTargetClass();    Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");    Class<?> proxySuperClass = rootClass;    if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {      proxySuperClass = rootClass.getSuperclass();      Class<?>[] additionalInterfaces = rootClass.getInterfaces();      for (Class<?> additionalInterface : additionalInterfaces) {        this.advised.addInterface(additionalInterface);      }    }    // Validate the class, writing log messages as necessary.    validateClassIfNecessary(proxySuperClass, classLoader);    // Configure CGLIB Enhancer...    Enhancer enhancer = createEnhancer();    if (classLoader != null) {      enhancer.setClassLoader(classLoader);      if (classLoader instanceof SmartClassLoader &&          ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {        enhancer.setUseCache(false);      }    }    enhancer.setSuperclass(proxySuperClass);    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);    enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));    Callback[] callbacks = getCallbacks(rootClass);    Class<?>[] types = new Class<?>[callbacks.length];    for (int x = 0; x < types.length; x++) {      types[x] = callbacks[x].getClass();    }    // fixedInterceptorMap only populated at this point, after getCallbacks call above    enhancer.setCallbackFilter(new ProxyCallbackFilter(      this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));    enhancer.setCallbackTypes(types);    // Generate the proxy class and create a proxy instance.    return createProxyClassAndInstance(enhancer, callbacks);  }  catch (CodeGenerationException | IllegalArgumentException ex) {    throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +                                 ": Common causes of this problem include using a final class or a non-visible class",                                 ex);  }  catch (Throwable ex) {    // TargetSource.getTarget() failed    throw new AopConfigException("Unexpected AOP exception", ex);  }}
对应的Interceptor

org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {  Object oldProxy = null;  boolean setProxyContext = false;  Object target = null;  TargetSource targetSource = this.advised.getTargetSource();  try {    if (this.advised.exposeProxy) {      // Make invocation available if necessary.      oldProxy = AopContext.setCurrentProxy(proxy);      setProxyContext = true;    }    // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...    target = targetSource.getTarget();    Class<?> targetClass = (target != null ? target.getClass() : null);    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);    Object retVal;    // Check whether we only have one InvokerInterceptor: that is,    // no real advice, but just reflective invocation of the target.    if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {      // We can skip creating a MethodInvocation: just invoke the target directly.      // Note that the final invoker must be an InvokerInterceptor, so we know      // it does nothing but a reflective operation on the target, and no hot      // swapping or fancy proxying.      Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);      retVal = methodProxy.invoke(target, argsToUse);    }    else {      // We need to create a method invocation...      retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();    }    retVal = processReturnType(proxy, target, method, retVal);    return retVal;  }  finally {    if (target != null && !targetSource.isStatic()) {      targetSource.releaseTarget(target);    }    if (setProxyContext) {      // Restore old proxy.      AopContext.setCurrentProxy(oldProxy);    }  }}

事物

org.springframework.transaction.interceptor.TransactionInterceptor#invoke

org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

咱们在Spring中能够应用申明式事物和编程式事物

  • @Transactional
  • 和编程式事物
多数据源的切换

org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource

缓存

org.springframework.cache.interceptor.CacheInterceptor#invoke

  • Cacheable
  • `CacheConfig
  • CacheEvict
  • CachePut
  • Caching
  • EnableCaching

Mybatis

为什么通过Mapper接口就可能调用,不须要写实现类

Mapper接口

创立MapperProxyFactory

org.apache.ibatis.binding.MapperRegistry#addMapper

  public <T> void addMapper(Class<T> type) {    if (type.isInterface()) {      if (hasMapper(type)) {        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");      }      boolean loadCompleted = false;      try {        knownMappers.put(type, new MapperProxyFactory<T>(type));        // It's important that the type is added before the parser is run        // otherwise the binding may automatically be attempted by the        // mapper parser. If the type is already known, it won't try.        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);        parser.parse();        loadCompleted = true;      } finally {        if (!loadCompleted) {          knownMappers.remove(type);        }      }    }  }

这一段先初始化MapperProxyFactory,并且解析mapper接口上的注解

获取Mapper

org.apache.ibatis.binding.MapperRegistry#getMapper

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {  final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);  if (mapperProxyFactory == null) {    throw new BindingException("Type " + type + " is not known to the MapperRegistry.");  }  try {    return mapperProxyFactory.newInstance(sqlSession);  } catch (Exception e) {    throw new BindingException("Error getting mapper instance. Cause: " + e, e);  }}

以后获取代理对象通过MapperProxyFactory来生成的

代理

org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.binding.MapperProxy<T>)

@SuppressWarnings("unchecked")protected T newInstance(MapperProxy<T> mapperProxy) {  return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}public T newInstance(SqlSession sqlSession) {  final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);  return newInstance(mapperProxy);}

查看对应的代理,能够看到通过Proxy#newProxyInstance来生成的代理对象,也就是走的JDK的动静代理

具体的Invocationhandler
public class MapperProxy<T> implements InvocationHandler, Serializable {  private static final long serialVersionUID = -6424540398559729838L;  private final SqlSession sqlSession;  private final Class<T> mapperInterface;  private final Map<Method, MapperMethod> methodCache;  public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {    this.sqlSession = sqlSession;    this.mapperInterface = mapperInterface;    this.methodCache = methodCache;  }  @Override  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    if (Object.class.equals(method.getDeclaringClass())) {      try {        return method.invoke(this, args);      } catch (Throwable t) {        throw ExceptionUtil.unwrapThrowable(t);      }    }    final MapperMethod mapperMethod = cachedMapperMethod(method);    return mapperMethod.execute(sqlSession, args);  }  private MapperMethod cachedMapperMethod(Method method) {    MapperMethod mapperMethod = methodCache.get(method);    if (mapperMethod == null) {      mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());      methodCache.put(method, mapperMethod);    }    return mapperMethod;  }}

具体的执行是执行的MapperProxy#invoke办法

所以Mapper接口有要求,不能是final类并且办法不能是final的,并且办法不能重载

Spring Cloud Feign

如果理解过Spring Cloud Feign应该能够晓得能够在对应的接口下面加FeignClient那么在调用的时候就会帮咱们主动负载平衡

@FeignClient(    value = AppConstant.APPLICATION_USER_NAME)public interface IUserClient {    /**     * 获取用户信息     *     * @param userId 用户id     * @return     */    @GetMapping(USER_INFO_BY_ID)    R<User> userInfoById(@RequestParam("userId") Long userId);

必定是做了代理,那么咱们查看代码探索一下Spring Cloud Feign是如何做的

创立FeignClientFactoryBean

org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClient

能够看到

BeanDefinitionBuilder definition = BeanDefinitionBuilder  .genericBeanDefinition(FeignClientFactoryBean.class);

创立了一个FeignClientFactoryBean所以会调用他的

初始化生成代理对象

org.springframework.cloud.openfeign.FeignClientFactoryBean#getObject

    public Object getObject() throws Exception {        return getTarget();    }

能够看到getTarget

<T> T getTarget() {  FeignContext context = applicationContext.getBean(FeignContext.class);  Feign.Builder builder = feign(context);//省略  String url = this.url + cleanPath();  Client client = getOptional(context, Client.class);  if (client != null) {    if (client instanceof LoadBalancerFeignClient) {      // not load balancing because we have a url,      // but ribbon is on the classpath, so unwrap      client = ((LoadBalancerFeignClient) client).getDelegate();    }    if (client instanceof FeignBlockingLoadBalancerClient) {      // not load balancing because we have a url,      // but Spring Cloud LoadBalancer is on the classpath, so unwrap      client = ((FeignBlockingLoadBalancerClient) client).getDelegate();    }    builder.client(client);  }  Targeter targeter = get(context, Targeter.class);  return (T) targeter.target(this, builder, context,                             new HardCodedTarget<>(type, name, url));}

调用了targeter#target来生成代理对象

public <T> T target(Target<T> target) {return build().newInstance(target);}

生成代理

feign.ReflectiveFeign#newInstance

public <T> T newInstance(Target<T> target) {  Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);  Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();  List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();  for (Method method : target.type().getMethods()) {    if (method.getDeclaringClass() == Object.class) {      continue;    } else if (Util.isDefault(method)) {      DefaultMethodHandler handler = new DefaultMethodHandler(method);      defaultMethodHandlers.add(handler);      methodToHandler.put(method, handler);    } else {      methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));    }  }  InvocationHandler handler = factory.create(target, methodToHandler);  T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),                                       new Class<?>[] {target.type()}, handler);  for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {    defaultMethodHandler.bindTo(proxy);  }  return proxy;}

能够看到也是通过JDK的动静代理来生成代理对象的

InvocationHandler如下

@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  if ("equals".equals(method.getName())) {    try {      Object otherHandler =        args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;      return equals(otherHandler);    } catch (IllegalArgumentException e) {      return false;    }  } else if ("hashCode".equals(method.getName())) {    return hashCode();  } else if ("toString".equals(method.getName())) {    return toString();  }  return dispatch.get(method).invoke(args);}

会通过办法来散发做负载平衡

总结

长处

  • 能把代理对象和实在被调用的指标对象拆散
  • 升高了零碎的耦合度,易于扩大
  • 可能爱护指标对象
  • 加强指标对象的性能

毛病

  • 零碎类数目减少
  • 客户端和指标对象之间减少了代理对象,申请处理速度会变慢,减少了零碎的复杂度

Spring中的代理抉择准则

  1. Bean中有实现接口的时候,Spring会应用JDK的动静代理
  2. Bean没有实现接口的时候,Spring会抉择CGLIB
  3. Spring能够通过配置强制应用CGLIB,只需在Spring的配置文件中退出这个代码
<aop:aspectj-autoproxy proxy-target-class="true">
我的笔记仓库地址gitee 快来给我点个Star吧