跟着Spring大厂学抽象

简介: 跟着Spring大厂学抽象

前言

新的一年的学习,学习一项新知识,最好的方法就是有优秀的案例配合学习,不仅能够帮助你学习新知识,而且还可以让你了解到它能运用到什么情况下的场景。建议大家学习新知识的时候,不要仅限于理论,配合优秀的案例场景可以事半功倍。

这次想带大家了解的是抽象工厂模式(Abstract Factory)的实现,要说案例,那肯定还是Spring的案例是最适合的。新手学习基础,进阶学习源码,适用于任何一个阶段的开发者。

基本概念

抽象工厂提供了一种方式,让具有同一主题的单独的工厂给封装起来。在我们正常使用中,客户端程序需要创建抽象方法的具体实现,然后使用抽象工厂作为接口来创建具体的对象。而客户端也不需要关心其中的具体实现,因为调用的是统一且通用的接口。

举例一下Spring AOP的具体实现

  • interface接口 — org.springframework.aop.framework.AopProxyFactory
  • class唯一实现 — org.springframework.aop.framework.DefaultAopProxyFactory
package org.springframework.aop.framework;
public interface AopProxyFactory {
   /**
    * 为给定的AOP配置创建AopProxy。
    */
   AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}

这是一个interface接口,它有一个返回类型为AopProxy,method名称为createAopProxy的方法,但凡是实现了AopProxyFactory这个接口的,都需要实现createAopProxy方法。

AopProxyFactory这个接口的作用就是创建一个CGLIB代理或JDK动态代理,因此它的返回类型是比较罕见的interface类型。

public interface AopProxy {
   Object getProxy();
   Object getProxy(@Nullable ClassLoader classLoader);
}

实际用法上,到时候只需要调用getProxy方法就行,不需要理会返回的这个AopProxy对象是一个CGLIB代理对象,还是一个JDK动态代理对象。

在这个上面,无论是JdkDynamicAopProxy动态代理,还是ObjenesisCglibAopProxy代理,他们都 implements 了AopProxy这个接口类,也是一种抽象工厂模式。因此无论是返回JdkDynamicAopProxy对象,还是返回ObjenesisCglibAopProxy对象,都可以使用AopProxy这个接口类作为统一的返回类型。

这就是一种抽象,而在SpringAOP中,需要创建一个CGLIB代理或JDK动态代理,所有DefaultAopProxyFactory这一个类继承且实现了它。以下是DefaultAopProxyFactory的实现类源码:

package org.springframework.aop.framework;
import java.io.Serializable;
import java.lang.reflect.Proxy;
import org.springframework.aop.SpringProxy;
/**
 * 
 * 对于给定的AdvisedSupport实例,如果下列情况之一为真,则创建CGLIB代理:
 * 1.优化标志被设置
 * 2.设置proxyTargetClass标志
 * 3.未指定代理接口
 * 通常,指定proxyTargetClass来强制使用CGLIB代理,或者指定一个或多个接口来使用JDK动态代理。
 */
@SuppressWarnings("serial")
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
   @Override
   public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
      if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
         Class<?> targetClass = config.getTargetClass();
         if (targetClass == null) {
            //TargetSource不能确定目标类:创建代理需要接口或目标。
            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);
      }
   }
   /**
    * 确定所提供的AdvisedSupport是否只指定了SpringProxy接口(或者根本没有指定代理接口)。
    */
   private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
      Class<?>[] ifcs = config.getProxiedInterfaces();
      return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
   }
}

SpringAOP中默认的AopProxyFactory实现,用于创建一个CGLIB代理或JDK动态代理。

根据源码可知,创建CGLIB代理,只需要满足任意一种条件即可

if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))
  • 1.优化标志被设置
  • 2.设置proxyTargetClass标志
  • 3.未指定代理接口

若三个条件都不满足,则创建Jdk动态代理。

但是在每个不同的业务中,不一定就需要跟AopProxyFactory一样,返回类型是一个interface,你可以是一个String,也可以是一个Object、Boolean都可以。

但是在命名规范上是非常有讲究的

  1. 类命名需要以Factory结尾
  2. 类命名前面的名词,一般是被创建的对象,比如AopProxyFactory,那么抽象的方法返回类型就是AopProxy
  3. 方法命名,一般都是createXxx、newXxx、getXxx、buildXxx

结束

抽象工厂模式的学习就告一段落了,感兴趣的同学可以打开idea,更深层次的去了解AopProxyFactory的源码,以及他们模式的使用。

相关文章
|
弹性计算 网络协议 IDE
Nacos报错问题之集群开启鉴权无法注册如何解决
Nacos是一个开源的、易于部署的动态服务发现、配置管理和服务管理平台,旨在帮助微服务架构下的应用进行快速配置更新和服务治理;在实际运用中,用户可能会遇到各种报错,本合集将常见的Nacos报错问题进行归纳和解答,以便使用者能够快速定位和解决这些问题。
1433 1
|
监控 Java Linux
JVM调优
JVM调优
617 0
|
存储 Java BI
XXL-JOB定时任务知识点和应用实例
XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。该处只是介绍xxl_job的一下基础知识和使用的实例,具体的安装调试请参照对应的最新的官方文档,中文开源地址:https://www.xuxueli.com/xxl-job
4451 0
|
SQL 分布式计算 API
Spark学习------SparkSQL(概述、编程、数据的加载和保存)
Spark学习------SparkSQL(概述、编程、数据的加载和保存)
337 2
|
3月前
|
Java 数据库连接 开发者
Spring Framework 核心技术详解
本文档旨在深入解析 Java Spring Framework 的核心技术原理与应用。与侧重于快速开发的 Spring Boot 不同,本文将聚焦于 Spring 框架本身的设计理念、核心容器、控制反转(IoC)、面向切面编程(AOP)、数据访问与事务管理等基础且强大的模块。通过理解这些核心概念,开发者能够更深刻地领悟 Spring 生态系统的设计哲学,并具备解决复杂企业级应用开发问题的能力。
283 4
|
4月前
|
缓存 NoSQL Java
一些高频面试题
这篇文章整理了一些高频面试题
176 0
|
存储 SQL 算法
跑批为什么这么难
业务系统产生的明细数据需经加工处理以支持企业经营,此过程称作“跑批”,常在夜间进行以免影响生产系统。跑批任务涉及大量数据及复杂计算,导致耗时较长。开源计算引擎SPL可直接基于文件系统计算,提供更优算法与存储机制,显著提升跑批效率。例如,L银行贷款协议跑批任务从2小时缩短至10分钟,性能提高12倍;P保险公司车险业务的历史保单关联任务从近2小时缩短至17分钟,速度提升近7倍;T银行贷款跑批任务提速204倍。
|
小程序 调度 数据库
jeecg-boot集成xxl-job调度平台,每秒/每分钟/手动都能执行成功,但是设置固定时间不触发?
jeecg-boot集成xxl-job调度平台,每秒/每分钟/手动都能执行成功,但是设置固定时间不触发?
|
Java Shell 应用服务中间件
Mac系统下配置环境变量:Javajdk、maven、tomcat 环境变量配置及对应配置文件
这篇文章介绍了如何在Mac系统下配置Java JDK、Maven和Tomcat的环境变量,包括配置文件的选择、解决环境变量在zsh shell中无效的问题、查看和设置系统环境变量的方法,以及JDK和Maven的下载、配置和测试步骤。
5703 1
Mac系统下配置环境变量:Javajdk、maven、tomcat 环境变量配置及对应配置文件
|
编解码 NoSQL Java