Spring5应用之高级注解开发

news2025/1/23 8:08:43

作者简介:☕️大家好,我是Aomsir,一个爱折腾的开发者!
个人主页:Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客
当前专栏:Spring5应用专栏_Aomsir的博客-CSDN博客

文章目录

  • 参考文献
  • 前言
  • @Configuration
  • 开发步骤:
  • @Bean
    • 开发步骤
    • 自定义类型
    • 细节分析
  • @ComponentScan
  • 纯注解事务开发
  • AOP纯注解开发
  • 总结

参考文献

  • 孙哥suns说Spring5~学不会Spring? 因为你没找对人~孙帅
  • Spring官方文档

前言

在上一篇文章中,我们详细介绍了Spring2.x提供的一系列基础注解,并探讨了如何使用这些注解来简化开发。这些注解在Spring框架中的作用不可忽视,它们为开发者提供了更便捷的方式来管理组件、依赖注入以及其他关键方面的配置。本文将继续探讨Spring注解开发,更深入地了解这些强大的工具如何加速开发过程并提高代码质量。

@Configuration

在Spring3.x中引入了一项重要的新注解,即 @Configuration,它通常被称为配置类。这个注解的作用非常强大,它允许我们将Java类标记为配置Bean,以代替繁琐的XML配置文件。实际上,@Configuration是@Component注解的一种特殊形式。

开发步骤:

  1. 创建配置类:首先,创建一个Java类,并在其上标记 @Configuration 注解,将其变为一个配置Bean。
  2. 编写配置代码:在配置类中,编写Spring配置代码,包括Bean定义、依赖注入等。
  3. 进行测试:编写测试代码来验证配置类中的配置是否按预期工作。

通过使用 @Configuration 注解,我们可以更加方便地管理应用程序的配置,减少对XML配置文件的依赖,同时提高了代码的可维护性和可读性

@Configuration
public class AppConfig {
}
public class TestAnnotation2 {

    /**
     * 测试 @Configuration 注解
     */
    @Test
    public void test1() {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    }
}

在这里插入图片描述

@Bean

@Bean注解通常用于配置类中,用于声明和创建Bean。它与@Component注解相似,都能够将类标记为由Spring管理的组件。然而,@Bean注解在某些方面与@Component有一些关键的不同之处。

  • 区分简单对象和复杂对象:在Spring开发中,我们通常将对象分为两类:简单对象和复杂对象。
    • 简单对象:这些对象可以直接使用new操作符进行创建,例如UserUserServiceUserDAO等。
    • 复杂对象:这些对象不适合直接使用new操作符创建,通常是因为它们依赖其他Bean或需要进行复杂的初始化过程,比如SqlSessionSqlSessionFactory等。

@Bean注解主要用于声明和创建复杂对象,因为它允许我们在配置类中定义复杂对象的初始化和依赖关系。

请注意,即使只有类文件可用,并且需要使用注解驱动的开发,也可以使用@Bean注解来定义Bean
在这里插入图片描述

开发步骤

  • 创建配置Bean,按照上图要求书写方法
  • 编写测试方法进行验证
@Configuration
public class AppConfig {

    /**
     * 创建 简单对象
     * @return User
     */
    @Bean
    public User user() {
        return new User();
    }

    @Bean
    public Connection connection() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/blog?useSSL=false&serverTimezone=UTC","root","123456");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}
public class TestAnnotation2 {
    /**
     * 测试 @Bean 注解 简单对象
     */
    @Test
    public void test2() {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = ctx.getBean("user",User.class);
        System.out.println(user);
    }

    /**
     * 测试 @Bean 注解 复杂对象
     */
    @Test
    public void test3() {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

        Connection connection = ctx.getBean(Connection.class);

        System.out.println("connection = " + connection);
    }
}

在这里插入图片描述
在这里插入图片描述

自定义类型

对于自定义数据类型,难免会遇到这种情况就是自定义类型的依赖注入,对于我们依赖方和被依赖方都使用@Bean的情况下,我们需要进行依赖注入应该怎么办?Spring会帮我们进行自动注入

  • 依赖方在方法体内用Set直接注入被依赖方即可,Spring会帮我们进行处理
  • 依赖方方法形参写上被依赖方,然后直接用Set方法注入,Spring也会帮我们进行处理,原理一致
    如下两段代码演示即可
@Configuration
public class AppConfig {

    @Bean
    public UserDAO userDAO() {
        return new UserDAOImpl();
    }

    @Bean
    public UserService userService() {
        UserService userService = new UserServiceImpl();

        // 这里可以直接注入,Spring会帮我们在容器中找
        userService.setUserDao(userDAO);
        return userService;
    }
}
@Configuration
public class AppConfig {

    @Bean
    public UserDAO userDAO() {
        return new UserDAOImpl();
    }

    @Bean
    public UserService userService(UserDAO userDAO) {
        UserService userService = new UserServiceImpl();

        // 也可以写在方法参数中,Spring也会帮我们进行注入
        userService.setUserDao(userDAO);
        return userService;
    }
}

细节分析

  • 自定义id值可以直接修方法名,也可以使用注解参数@Bean("u")
  • 控制对象的创建次数,可以在方法上标注@Scope并设置对应的值

@ComponentScan

@ComponentScan 注解用于扫描并注册 Spring Bean。它等同于 XML 配置中的 <context:component-scan base-package="" /> 元素。通过在配置类上使用 @ComponentScan 注解,可以告诉 Spring 哪些包需要被扫描,从而将这些包中的 Bean 注入容器中。

此注解具有多个属性,可用于指定包含和排除的规则等。下面是一个示例用法,其中包含和排除是多种多样的,具体的使用方法可以参考官方文档

@Configuration
@ComponentScan(basePackages = "com.aomsir.basic",
               excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class)},
               includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)},
               useDefaultFilters = false)
public class AppConfig {
}

纯注解事务开发

在先前的 Spring 事务开发中,我们通常需要在 XML 配置文件中设置数据源dataSourceTransactionManager 等事务相关的配置。

然而,现在我们可以使用纯注解方式来管理事务,只需要创建一个配置类进行配置。接下来,只需在需要事务支持的方法或业务类上添加 @Transactional 注解即可,无需再涉及繁琐的配置。

这种方式极大地简化了事务管理,提高了代码的可维护性

@Configuration
@EnableTransactionManagement  // 开启事务
public class TransactionAutoConfiguration {
    @Autowired
    private DataSource dataSource;
    
    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager() {
        DataTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

AOP纯注解开发

在先前的AOP动态代理开发中,我们已经通过注解方式大大简化了很多内容,如切面类、切入点等。然而,仍然需要在配置文件中声明 <aop:aspectj-autoproxy /> 标签,以允许Spring启用AspectJ,以便使用注解来编写切面。但是,现在我们可以通过纯注解方式来进一步简化这些操作,包括启用AOP。

这种方式极大地减少了XML配置的需求,使AOP编程更加直观和便于维护

@Configuration
@ComponentScan(basePackages = "com.aomsir.basic.aop")
@EnableAspectJAutoProxy    // 允许Aspect - AOP,SpringBoot已经做了这一步
public class AppConfig {

}
@Aspect
@Component
public class MyAspect {

    private static final Logger log = LoggerFactory.getLogger(MyAspect.class);

    @Pointcut("execution(* com.aomsir.basic.aop..*.*(..))")
    public void pointCut(){}

    // 等价于invoke方法
    @Around("pointCut()")
    public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("----log----");
        Object ret = joinPoint.proceed();
        return ret;
    }
}


@Service
public class UserServiceImpl implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Override
    public void register(User user) {
        log.error("UserServiceImpl.register 业务运算+Dao的调用");
    }

    @Override
    public boolean login(String name, String password) {
        log.error("UserServiceImpl.login 业务运算+Dao的调用");
        return true;
    }
}

总结

这样,Spring中的注解编程完全分析完了。逐步将先前在Spring中使用配置文件的内容转换为注解方式是一种提高开发效率和可维护性的重要方法。Spring的注解编程使代码更加简洁和可读,同时减少了XML配置的需求。这将为以后学习和应用Spring Boot等框架提供坚实的基础

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1102037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JOSEF约瑟 10KV高压漏电保护继电器BLD-20 φ100mm 50-500mA 导轨安装

系列型号 BLD-20A高压漏电保护继电器 BLD-20高压漏电继电器 BLD-20高压漏电保护继电器 BLD-20X高压漏电保护装置 BLD-G20X高压漏电保护装置 BLD-20RG高压漏电保护继电器 用途 BLD-20漏电继电器(以下简称继电器)主用于交流电压1-10KV系统中,频率为50HZ,对供电系 统的漏…

【C语言】#define宏与函数的优劣对比

本篇文章目录 1. 预处理指令#define宏2. #define定义标识符或宏&#xff0c;要不要最后加上分号&#xff1f;3.宏的参数替换后产生的运算符优先级问题3.1 问题产生3.2 不太完美的解决办法3.3 完美的解决办法 4.#define的替换规则5. 有副作用的宏参数6. 宏与函数的优劣对比6.1 宏…

从0开始学Java:运算符(Operator)与标点符号(Separators)

文章目录 1. 运算符的分类2. 算术运算符3. 赋值运算符4. 关系运算符/比较运算符5. 逻辑运算符6. 条件运算符练习 7. 位运算符&#xff08;了解&#xff09;左移&#xff1a;<<右移&#xff1a;>>无符号右移&#xff1a;>>>按位与&#xff1a;&按位或&…

阿里云优惠券(代金券)免费领取方法及使用教程分享

阿里云优惠券是阿里云提供给用户的一种优惠凭证&#xff0c;通常包括代金券和折扣券&#xff0c;领取之后支付订单时可以抵扣或者打折&#xff0c;是阿里云的一种重要优惠方式。本文将为大家详细介绍阿里云优惠券的免费领取方法及使用教程&#xff0c;帮助大家在购买阿里云产品…

qt 读取txt文本内容时,中文乱码

项目场景&#xff1a; 项目中&#xff0c;需要在TF卡中做类似txt阅读器的功能&#xff0c;因为app是在嵌入式系统下运行的&#xff0c;发现当读取txt的文本格式为ANSI时&#xff0c;中文的显示是乱码&#xff0c;故记录下解决方法 问题解决 中文乱码问题还是涉及到编码问题&…

Steam通过短信验证来遏制带有恶意软件的更新

导语段落 近期&#xff0c;Steam平台上的游戏开发者账户遭受了来自恶意软件的更新攻击&#xff0c;为了应对这一问题&#xff0c;Valve公司宣布将实施额外的安全措施&#xff0c;其中包括基于短信的确认码验证。本文将为大家介绍这一新措施以及其对游戏开发者和玩家的影响。 短…

ORA-12541:TNS:no listener 无监听程序

问题截图 解决方法 1、删除Listener 新建一个新的 2、主机为服务器ip 3、设置数据库环境 只需要设置实例名不需要设置路径 4、服务命名 一样设置为ip 服务名与监听名一直 eg&#xff1a;orcl

React中的key有什么作用

一、是什么 首先&#xff0c;先给出react组件中进行列表渲染的一个示例&#xff1a; const data [{ id: 0, name: abc },{ id: 1, name: def },{ id: 2, name: ghi },{ id: 3, name: jkl } ];const ListItem (props) > {return <li>{props.name}</li>; };co…

Windows窗口过程

一、窗口类&#xff08;WNDCLASS&#xff09; 定义&#xff1a;窗口类是一个属性集&#xff0c;是Windows编程中用于创建窗口的模板。窗口类包含了窗口的各种信息的数据结构&#xff0c;每个窗口都具有窗口类&#xff0c;每个窗口都是基于自己的窗口类来进行创建窗口的。每一个…

【前端】Js

目 录 一.前置知识第一个程序JavaScript 的书写形式注释输入输出 二.语法概览变量的使用理解 动态类型基本数据类型 三.运算符算术运算符赋值运算符 & 复合赋值运算符自增自减运算符比较运算符逻辑运算符位运算移位运算 四.条件语句if 语句三元表达式switch 五.循环语句whi…

云技术分享 | 快速构建 CodeWhisperer 代码生成服务,让 AI 辅助编程

前言 Amazon CodeWhisperer 是 2023 年 4 月份发布的一款通用的、机器学习驱动的代码生成器服务&#xff0c;CodeWhisperer 经过数十亿行 Amazon 和公开可用代码的训练&#xff0c;可以理解用自然语言&#xff08;英语&#xff09;编写的评论&#xff0c;可在集成式开发环境 (…

Unity笔记--渲染顺序

目录 Unity中的渲染顺序一、Camera层二、透明类型&#xff08;先渲染不透明&#xff09;三、物体的SortingLayer&#xff08;越小越先渲染&#xff09;四、sorting order&#xff08;越小越先渲染&#xff09;五、RenderQueue &#xff08;越小越优先&#xff09;六、距离相机z…

在 rider 里用配置 Perforce(P4)的注意事项

整个配置界面里&#xff0c;关键就配2处位置&#xff0c;但是都有些误导性。 1是连接形参的4个参数都得填&#xff0c;字符集看你项目的要求&#xff0c;这里工作区其实指的是你的工作空间&#xff0c;还不如显示英文的 Workspace 呢&#xff0c;搞得我一开始没填&#xff0c;…

Spring事件ApplicationEvent源码浅读

文章目录 demo应用实现基于注解事件过滤异步事件监听 源码解读总结 ApplicationContext 中的事件处理是通过 ApplicationEvent 类和 ApplicationListener 接口提供的。如果将实现了 ApplicationListener 接口的 bean 部署到容器中&#xff0c;则每次将 ApplicationEvent 发布到…

windows电脑彻底删除文件怎么恢复?可尝试这2种恢复办法!

在使用windows电脑过程中&#xff0c;误删重要文件是时常发生的事情。如果幸运的话&#xff0c;误删的文件可以在回收站中还原。而有时&#xff0c;这些文件是被彻底删除的&#xff0c;并不会经过回收站。windows彻底删除文件怎么恢复&#xff1f; windows彻底删除了文件&…

第四章 Istio出口流量管理

文章目录 访问外部服务Envoy 代理将请求传递给网格外服务配置服务条目以提供对外部服务的受控访问访问外部 HTTP 服务 直接访问外部服务 出口网关清理 HTTP 网关其他 访问外部服务 为了更好的做好网络访问控制&#xff0c;k8s结合Istio出口网络升级示意图 来自 Istio 的 pod…

linux入门到精通-第四章-gcc编译器

目录 参考gcc概述gcc的工作流程 参考 gcc编译器 gcc概述 编辑器vi、记事本)是指我用它来写程序的 (编辑码)&#xff0c;而我们写的代码语句&#xff0c;电脑是不懂的&#xff0c;我们需要把它转成电脑能懂的语句&#xff0c;编译器就是这样的转化工具。就是说&#xff0c;我…

4.MidBook项目经验之MonogoDB和easyExcel导入导出

1.数据字典(固定的数据,省市级有层级关系的) //mp表如果没有这个字段,防报错,eleUI需要这个字段TableField(exist false) //父根据id得到子数据 ,从controller开始自动生成代码-->service//hasChildren怎么判断,只需要判断children的parentid的count数量>0就可以了//优化…

uniapp订单循环列表倒计时

目录 效果图片插件uni-countdown代码最后 效果图片 插件uni-countdown 地址 代码 <template><view class""><!-- 下面循环两个列表 --><view class"item" v-for"(item, index) in listData" :key"index">&…

企业c#语言源代码防泄密解决方案

在当今数字化时代&#xff0c;企业的核心业务往往依赖于软件应用程序。为了保护企业的知识产权和敏感信息&#xff0c;源代码的保密至关重要。对于制造类企业尤其是智能制造业来讲&#xff0c;最近几年是高速发展的时期&#xff0c;很多公司在做工厂流水线设备时&#xff0c;就…