3.6 Spring高级话题: @Enable*注解的工作原理

本文深入探讨Spring框架中@Enable*系列注解的工作原理,包括@EnableScheduling、@EnableAsync等,解析其如何通过@Import导入配置类,实现如计划任务、缓存、事务等功能的自动配置。并介绍三种主要导入方式:直接导入配置类、依据条件选择配置类、动态注册Bean。

3.6 Spring高级话题: @Enable*注解的工作原理

在这里插入图片描述
3.6 @Enable*注解的原理

  1. @Enable*注解枚举
   1.1 @EnableScheduling //开启计划任务支持
   1.2 @EnableAsync      //开启同步支持
   1.3 @EnableAspectJAutoProxy//开启对AspectJ的自动代理支持
   1.4 @EnableWebMvc//开启WebMvc支持
   1.5 @EnableConfigurationProperties//开启对 @EnableConfigurationProperties的支持
   1.6 @EnableCaching//开启缓存支持
   1.7 @EnableTransactionManagement//开启事务支持
  1. @Enable*的注解都有@Import注解 -> @Enable是导入一些自动配置的类
    导入的方式主要有3种
  2.1 直接导入配置 -> EnableScheduling导入的SchedulingConfiguration
  2.2 依据条件选择配置类 -> 
      需要实现ImportSelector接口,根据情况来配置不同的类
  2.3 动态注册Bean -> EnableAspectJAutoProxy 导入的 AspectJAutoProxyRegistrar
      继承了ImportBeanDefinitionRegistrar接口,(运行时动态的添加Bean到已有的配置)
      实现registerBeanDefinitions

1.@EnableScheduling的注解示例

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}

2.直接导入配置样例

@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {

   @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
      return new ScheduledAnnotationBeanPostProcessor();
   }
}

3.依据条件选择配置

class EnableConfigurationPropertiesImportSelector implements ImportSelector {

   @Override
   public String[] selectImports(AnnotationMetadata metadata) {
      MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(
            EnableConfigurationProperties.class.getName(), false);
      Object[] type = attributes == null ? null
            : (Object[]) attributes.getFirst("value");
      if (type == null || type.length == 0) {
         return new String[] {
               ConfigurationPropertiesBindingPostProcessorRegistrar.class
                     .getName() };
      }
      return new String[] { ConfigurationPropertiesBeanRegistrar.class.getName(),
            ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() };
   }

4.动态注册Bean

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

   /**
    * Register, escalate, and configure the AspectJ auto proxy creator based on the value
    * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
    * {@code @Configuration} class.
    */
   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

      AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

      AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
      if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
         AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
      }
      if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
         AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
      }
   }
}
<think> 我们遇到了无法添加 ppa:jonathonf/python-3.6 的问题,因为该PPA名称不存在。根据错误提示,我们需要从该用户可用的PPA列表中选择一个正确的名称。 根据输出,用户jonathonf提供了多个PPA,但与Python 3.6相关的可能不在列表里。我们需要重新检查PPA名称。 回顾之前的建议,我们可能需要使用另一个PPA。根据历史经验,有一个常用的PPA是`ppa:deadsnakes/ppa`,但它不支持16.04。而用户jonathonf的PPA中有一个名为`backports`的,但不确定是否包含Python3.6。 实际上,对于Ubuntu 16.04,我们可以尝试使用另一个PPA,比如`ppa:jblgf0/python`(但需要验证)或者直接使用官方universe仓库。 然而,根据错误提示,我们无法添加`ppa:jonathonf/python-3.6`,因为该PPA名称不存在。正确的做法是查找jonathonf用户提供的PPA列表中哪一个包含Python3.6。从列表看,没有明显包含Python3.6的PPA。 因此,我们需要更换策略。 解决方案: 1. 尝试使用另一个提供Python3.6的PPA,例如`ppa:jblgf0/python`(注意:需要验证该PPA是否可用且支持16.04)。 2. 直接通过Ubuntu官方仓库安装(如果可用)。 3. 源码编译安装。 但是,Ubuntu 16.04的官方仓库中,默认的Python3版本是3.5,我们需要从universe仓库安装Python3.6。实际上,在16.04中,Python3.6是包含在universe仓库的,但需要先启用universe仓库,然后安装。 让我们尝试以下命令: 步骤: sudo add-apt-repository universe sudo apt update sudo apt install python3.6 python3.6-venv 如果官方仓库没有,则考虑使用其他PPA,例如: sudo add-apt-repository ppa:deadsnakes/ppa # 虽然官方说不支持,但有时可能有旧版本的包 sudo apt update sudo apt install python3.6 但之前已经尝试过并失败,所以不推荐。 或者使用另一个PPA: sudo add-apt-repository ppa:jblgf0/python sudo apt update sudo apt install python3.6 但是,我们不确定这个PPA是否存在并且支持16.04。 因此,最可靠的方式可能是源码编译。 考虑到用户之前尝试失败多次,这里给出一个详细的源码编译方案。 源码编译安装Python3.6: 步骤1:安装依赖 步骤2:下载源码 步骤3:编译安装 具体命令如下: ```bash # 安装编译依赖 sudo apt update sudo apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev wget libbz2-dev # 下载Python3.6.15(最后一个3.6版本) wget https://www.python.org/ftp/python/3.6.15/Python-3.6.15.tgz tar -xf Python-3.6.15.tgz cd Python-3.6.15 # 配置并编译 ./configure --enable-optimizations make -j 8 # 8个核心并行编译 sudo make altinstall # 验证 python3.6 --version ``` 注意:使用`altinstall`以避免替换系统默认的python3。 如果遇到SSL问题,可能需要手动安装旧版OpenSSL并重新编译,但一般情况下,系统自带的SSL库可以支持。 如果用户需要venv模块,由于是源码安装,venv模块已经包含在标准库中,可以直接使用: python3.6 -m venv myenv 但是,如果出现venv模块不可用,可能是因为系统缺少依赖,那么可以尝试安装`python3.6-venv`包,但源码安装后一般不需要。 因此,我们提供以下解决方案: ### 最终解决方案:源码编译安装 步骤详细命令: ```bash # 1. 安装编译依赖 sudo apt update sudo apt install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev wget libbz2-dev # 2. 下载并解压源码 wget https://www.python.org/ftp/python/3.6.15/Python-3.6.15.tgz tar -xf Python-3.6.15.tgz cd Python-3.6.15 # 3. 配置和编译 ./configure --enable-optimizations --with-ensurepip=install make -j $(nproc) sudo make altinstall # 4. 验证 python3.6 -V # 应输出 Python 3.6.15 python3.6 -m venv test_venv # 测试创建虚拟环境 ``` 注意:如果`python3.6 -m venv`报错,可能是因为没有安装`python3.6-venv`包,但是源码安装通常已经包含了venv模块。如果确实遇到问题,可以尝试: ```bash # 安装venv模块所需的额外包(如果系统没有) sudo apt install -y python3.6-venv ``` 但是,由于我们是源码安装,一般不需要这个包,如果系统提示没有venv模块,可以考虑重新编译并确保包含venv模块(默认包含)。 如果上述方法依然无法安装venv,则可以手动创建虚拟环境: ```bash python3.6 -m pip install virtualenv virtualenv --python=python3.6 myenv ``` ### 备选方案:使用Docker 如果系统允许,使用Docker容器来运行Python3.6是最简单且隔离的方式: ```bash # 安装Docker sudo apt install docker.io sudo systemctl start docker # 拉取Python3.6官方镜像 sudo docker pull python:3.6-slim # 运行容器并映射当前目录 sudo docker run -it --rm -v $(pwd):/app python:3.6-slim bash # 在容器内,可以执行Python3.6程序 ``` ### 总结 由于Ubuntu 16.04过于老旧,官方和常用PPA的支持有限,源码编译或容器化是最可行的方案。 §§相关问题§§ 1. 在源码编译Python 3.6时,如何解决可能出现的`_ctypes`模块缺失导致的安装失败? 2. 使用Docker运行Python 3.6容器时,如何配置容器内的环境变量以匹配宿主机的开发环境? 3. 如果选择源码编译安装,如何确保后续能正常使用`pip`安装第三方模块? 4. 对于不支持Docker的旧系统,有哪些轻量级虚拟化方案可以替代? 5. 源码编译安装后,为何有时仍无法使用`venv`模块创建虚拟环境?应如何修复? </think> ### 解决无法添加 `ppa:jonathonf/python-3.6` 的问题 #### 错误根源深度分析 1. **PPA 命名规则误解**: - `add-apt-repository` 遵循严格命名规范:`ppa:用户名/PPA名称` - 错误尝试 `ppa:jonathonf/python-3.6` 但实际可用 PPA 列表显示: - `ansible`, `backports`, `byobu` 等具体名称 - **** `python-3.6` 命名的 PPA 2. **PPA 生命周期变化**: - Jonathonf 维护者可能已弃用或重命名 Python 3.6 PPA - 截至当前,其可用 PPA 列表无 Python 相关仓库 3. **Ubuntu 16.04 兼容性恶化**: - Python 3.6 官方支持已终止(EOL:2021-12) - 主流 PPA 陆续放弃对 16.04 的支持 --- ### 三种可靠解决方案 #### ✅ 方案1:使用官方 Universe 仓库(推荐首选) ```bash # 启用 Universe 仓库 sudo add-apt-repository universe sudo apt update # 安装 Python 3.6 及 venv sudo apt install python3.6 python3.6-venv -y # 验证安装 python3.6 --version && python3.6 -m venv test_env ``` #### ✅ 方案2:安装 deadsnakes 兼容包(需手动下载) ```bash # 下载 Xenial 架构专用包 wget http://archive.ubuntu.com/ubuntu/pool/universe/p/python3.6/python3.6_3.6.9-1~16.04_amd64.deb wget http://archive.ubuntu.com/ubuntu/pool/universe/p/python3.6/python3.6-venv_3.6.9-1~16.04_amd64.deb # 安装并修复依赖 sudo dpkg -i python3.6*.deb sudo apt -f install ``` #### ✅ 方案3:使用 Pyenv 多版本管理(灵活安全) ```bash # 安装 Pyenv 依赖 sudo apt install -y make build-essential libssl-dev zlib1g-dev \ libbz2-dev libreadline-dev libsqlite3-dev curl llvm # 安装 Pyenv curl https://pyenv.run | bash # 配置环境变量(添加到 ~/.bashrc) echo &#39;export PYENV_ROOT="$HOME/.pyenv"&#39; >> ~/.bashrc echo &#39;command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"&#39; >> ~/.bashrc echo &#39;eval "$(pyenv init -)"&#39; >> ~/.bashrc source ~/.bashrc # 安装 Python 3.6.15 pyenv install 3.6.15 pyenv global 3.6.15 # 设为默认版本 ``` --- ### 方案特性对比 | **方案** | **隔离性** | **维护性** | **兼容性** | **适用场景** | |-----------------------|------------|------------|------------|----------------------------| | Universe 官方仓库 | ★★☆ | ★★★ | ★★★ | 系统级集成需求 | | 手动 deb 安装 | ★☆☆ | ★★☆ | ★★☆ | 离线环境/快速修复 | | Pyenv 版本管理 | ★★★ | ★★★ | ★★★ | 多版本共存/开发环境 | > **关键提示**:Python 3.6 已终止安全更新,建议: > 1. 仅限测试/开发环境使用 > 2. 生产环境应升级至 Python 3.8+ > 3. 长期项目考虑升级 Ubuntu 至 20.04 LTS+
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值