Spring 面向切面

一、面向切面(AOP) 有时,在按数据的处理流程编写程序时,我们不得不关心流程之外的情况,比如异常处理安全或日志。这些部分与主要事务交织在一起,使得代码功能不清,造成了强耦合。 面向切片(Aspect-Oriented Programming)就是为解决这样的问题产生的技术。该技术把那些横向影响了应用多处的功能从被其影响的主要事物流程中分离开来,作为切面。使流程只需要关注其本身,而切片则通过其他方式织入程序。 二、面向切面的术语 正如面向对象有其术语一样,面向切面也有用于描述其技术的相关概念,在介绍 Spring 的面向切面前需要加以解释。 通知(Advice) 通知是切面所具有的行为,也就是不采用面向切面编程时,那些与主要事务无关,应该被抽离出来的代码段。 连接点(Join Point) 连接点是可以应用通知的地方,也就是能够执行切面所具有的行为的地方。 切点(Poincut) 切点是真正应用通知的地方,切点一定是连接点。 切面(Aspect) 切面是通知和切点的总和。当程序执行到切点所在的位置时,就会执行对应的通知。 引入(Introduction) 引入是作为切面的类作用到处理主要事务的类的过程。这一过程为处理主要事物的类引入了新的方法和属性,但却没有对这个类本身进行修改。 织入(Weaving) 织入是为了实现切面的引入而采取的操作。织入将切面引入目标对象,创建了融合切面和目标的代理对象。这一操作可以发生在编译期、类加载期和运行期,需要看具体的实现。Spring 会在运行期完成切面的织入。 三、Spring的AOP:利用切点表达式选择切点 通知和切点共同组成了切面,在这一部分将讲述如何确定切点的位置。我们使用的是称为切点表达式的语法规范,用这一表达式确定我们所指定的切点,以便之后通知的编写。 Spring AOP 使用的是 AspectJ 切点指示器中的一部分,包括如下的内容 AspectJ指示器 描述 arg() 限制连接点匹配参数为指定类型的执行方法 @args() 限制连接点匹配参数由指定注解标注的执行方法 execution() 用于匹配是连接点的执行方法 this() 限制连接点匹配AOP代理的bean引用为指定类型的类 target 限制连接点匹配目标对象为指定类型的类 @target() 限制连接点匹配特定的执行对象,这些对象对应的类要具有指定类型的注解 within() 限制连接点匹配指定的类型 @within() 限制连接点匹配指定注解所标注的类型(当使用Spring AOP时,方法定义在由指定的注解所标注的类里) @annotation 限定匹配带有指定注解的连接点 通过组合使用这些类似于函数的指示器的,就可以确定我们想要引入通知的连接点究竟在哪里。接下来我们通过一些示例展示切点表达式的使用。如 execution(* concert.Performance.perform(..)) 表示匹配一个在方法执行时触发的连接点,这个方法是 concert 包下的 Performance 类中名为 perform 的方法,不考虑方法的返回值和参数(匹配所有同名的 perform 方法)。 切点表达式中还可以使用与(&&)或(||)非(!)操作。如 execution(* concert.Performance.perform(..)) && within(concert.*) 表示同时满足是 concert 包下的类方法调用,并且满足上一条的条件的切点。...

一月 10, 2023 · 3 分钟 · 433 字 · Wokron

Spring 高级装配

上一篇文章已经讲解了 spring 依赖注入装配的方法。但是为了处理一些特殊的问题,或者为了更好地实现某些功能,spring 还提供了更多的装配设置。 一、条件化声明 Bean 让我们回到上一篇第一节的例子,假设这次我们需要在开发时使用 SQLite,而在生产环境使用 Oracle 要怎么办呢? 或许可以这样,我们在生产环境注意将 DBUtil Bean 改成 Oracle,把原来的部分注释掉,就像是这样。 @Bean public DBUtil databaseUtil() { // return new SQLiteUtil(); // for dev return new OracleUtil(); // for prod } 但这样做很明显是不合适的。如果许多组件都需要进行调整的话,修改上就会十分复杂,且很容易出错。 我们可以使用注释 @Profile 实现不同环境条件下选择不同的装配方式。这需要给带有 @Bean 或 @Configuration 注释的方法或类添加注释 @Profile("某某环境")。于是数据库的选择就可以改为如下形式: @Bean @Profile("dev") public DBUtil sqliteUtil() { return new SQLiteUtil(); } @Bean @Profile("prod") public DBUtil oracleUtil() { return new OracleUtil(); } 想要启用某个 Bean 需要设置环境。具体来说,这通过两个环境变量来实现,spring.profiles.default 和 spring.profiles.active。这两个值可以在许多地方定义。一种方式是在 properties 或 yaml 文件中定义,如...

一月 10, 2023 · 3 分钟 · 502 字 · Wokron

Spring 依赖注入

一、依赖注入 考虑这样一个例子,CustomerDAO 类使用了 DBUtil 类中的方法连接到 MySQL 数据库 public class CustomerDAO { private DBUtil databaseUtil = new DBUtil(); public Customer findCustomerByName(String name) { databaseUtil.doSomething() } } 假设现在想要改为使用 Oracle 数据库,需要怎么做?可以使用 OracleDBUtil 继承 DBUtil,并重写其相关方法。但是由于 CustomerDAO 中将 DBUtil 实例添加到其初始化过程中。因此想要修改的话还是需要对 CustomerDAO 本身进行修改。这违反了开-闭原则。 public class CustomerDAO { private DBUtil databaseUtil = new OracleDBUtil(); public Customer findCustomerByName(String name) { databaseUtil.doSomething() } } 为了使对 dbUtil 的修改不影响 CustomerDAO 本身,我们可以将实例的创建移到 CustomerDAO 之外。 public class CustomerDAO { private DBUtil databaseUtil; public CustomerDAO(DBUtil databaseUtil) { this....

一月 9, 2023 · 3 分钟 · 481 字 · Wokron

Django 创建表结构

一、对象关系映射(ORM) 面向对象与关系型数据库中的数据存储方式并不匹配,因此为了在编程中实现对数据库的操作,需要 ORM 技术将数据库中数据映射到对象之中。通过对对象的操作,做到对数据库的操作,从而实现增删改查等功能。 面向对象编程中,“关系”体现在类与其属性之间以及同一类的不同属性之间;而在关系型数据库中,“关系”体现在同一表中的不同列字段中。 二、django 的 ORM 实现 django 通过 models.Model 类来对应数据库中的表结构,如 class User(models.Model): 即表示了 User 类,也对应了数据库中的 user 表。django 会根据类的声明自动在数据库中建表。 django 用类中的属性来表示表的列字段。如 class User(models.Model): id = models.IntegerField(primary_key=True) name = models.CharField(max_length=50) password = models.CharField(max_length=50) 定义了 user 表的主键、名字、密码信息。 表间关系通过类与其属性表示,如 class User(models.Model): id = models.IntegerField(primary_key=True) name = models.CharField(max_length=50) password = models.CharField(max_length=50) courses = models.ManyToManyField(to="Course") courses 属性表示用户具有的课程,反映了用户与课程之间的关系。 三、类属性与数据库字段的对应 如上一节所述,django 建立了类属性与数据库字段之间的对应关系。常见的如 models.CharField models.TextField models.IntegerField models.FloatField 就对应了数据库中的 char(n),text,int,float 类型。不一一详述。 四、主键与外键 在表中要定义主键,作为该表一条记录的唯一标识。相应的,在 django 中定义主键需要在对应属性上添加 primary_key=True 参数。例如...

一月 9, 2023 · 2 分钟 · 234 字 · Wokron

用 Pytorch 搭建神经网络

一、前言 本文作为自己学习 pytorch 的记录。以搭建一个神经网络为例,介绍 pytorch 的基本使用。 本文不会讲 conda、python、pycharm 等的配置和使用,也不会讲各神经层的原理及使用。只是按照自己之前学习的理解,总结神经网络训练的基本流程。 本文所使用的例子是自己写的第一个神经网路,如下: import os.path import torch.utils.data from torch.utils.data import DataLoader from torch import nn from torch.utils.tensorboard import SummaryWriter from torchvision import transforms, datasets device = torch.device("cpu") if torch.cuda.is_available(): print("cuda available, use cuda to train module") device = torch.device("cuda") train_set = datasets.CIFAR10("./CIFAR10", transform=transforms.ToTensor(), download=True) test_set = datasets.CIFAR10("./CIFAR10", transform=transforms.ToTensor(), train=False, download=True) train_set_size = len(train_set) test_set_size = len(test_set) print(f"train set size: {train_set_size}") print(f"test set size: {test_set_size}") train_dataloader = DataLoader(train_set, 64, shuffle=True, drop_last=True) test_dataloader = DataLoader(test_set, 64) class MyModule(nn....

一月 2, 2023 · 5 分钟 · 884 字 · Wokron

MySQL 的中文插入问题

一、问题描述 在执行一个sql脚本的时候出现了这样的问题: ERROR 1366 (HY000): Incorrect string value: '\xA3\x8E\xE6\x9C\x89\xE5...' for column 'name_zh' at row 1 问题很明显是由于中文引起的。查看报错的语句: INSERT INTO `admin_menu` VALUES ('1', '/admin', 'AdminIndex', '首页', 'el-icon-s-home', 'AdminIndex', '0'); 是 “首页” 无法被识别。考虑是字符集的问题。 二、问题处理 情况一:数据库字符集与脚本所用字符集不一致 第一种可能是数据库所用的字符集和脚本字符集不一致,比如说建表时使用的字符集为 latin1,而脚本使用的却是 utf-8,这样就会导致错误。 输入命令,查看建库语句 SHOW CREATE DATABASE wj; +--------------+----------------------------------------------------------------------------------------------------------------------------------------+ | Database | Create Database | +--------------+----------------------------------------------------------------------------------------------------------------------------------------+ | white_jotter | CREATE DATABASE `wj` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ | +--------------+----------------------------------------------------------------------------------------------------------------------------------------+ 显示所用字符集为 utf8mb4,说明数据库字符集与脚本所用字符集一致。...

十二月 31, 2022 · 2 分钟 · 252 字 · Wokron