如何做幼儿园网站设计/网络推广员招聘
目录
- 一、AOP 动态代理切入方法
- (1) Aspect Oriented Programming
- (2) 切入点表达式
- 二、SpringBoot 项目扫描类
- (1) ResourceLoader 扫描类
- (2) Map 的 computeIfAbsent 方法
- (3) 反射几个常用 api
- ① 创建一个测试注解
- ② 创建测试 PO 类
- ③ 反射 api 获取指定类的指定注解信息
- (4) 返回第一个不为空的字符串
- (5) 判断一个【字符】是大写字母还是小写字母
- (6) 让英文单词的首字母变小写
- (7) 驼峰转下划线形式
- (8) GForeignTableInfo(外键表信息)
- (9) 遍历 Class 对象的全部属性
🍀 学习不使用数据库外键的情况下保证有关联的表之间的数据的一致性
一、AOP 动态代理切入方法
(1) Aspect Oriented Programming
🎄 AOP(Aspect Oriented Programming)面向切面编程
🎄 Spring 使用 AOP 技术封装了动态代理功能
🎄 它依赖 AspectJ 库
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.6</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
(2) 切入点表达式
🍀 ① 任意公共方法:
execution(public * *(..))
🍀 ② 方法名以 set 开头的全部方法:
execution(* set*(..))
🍀 ③ UserService 接口定义的全部方法:
execution(* com.guoqing.service.UserService.*(..))
🍀 ④ service 包下定义的全部方法(不包括子包):
execution(* com.guoqing.service.*.*(..))
🍀 ⑤ service 包下定义的全部方法(包括子包):
execution(* com.guoqing.service..*.*(..))
🍀 ⑥ 包含两个 String 类型参数的全部方法:
execution(* *(String, String))
🍀 ⑦ 只有一个 Serializable 参数的全部方法:
args(java.io.Serializable)
🍀 ⑧ service 包中的全部方法:
within(com.guoqing.service.*)
🍀 ⑨ service 包中的全部方法(包括子包):
within(com.guoqing.service..*)
@Slf4j
@Aspect
@Component
public class GForeignAspect {@Around("execution(* com.guoqing.service..*.remove*(..))")public Object handleRemove(ProceedingJoinPoint point) throws Throwable {Object target = point.getTarget();if (!(target instanceof IService)) return point.proceed();IService<?> service = (IService<?>) target;// MP 泛型的类型(genericType)是 PO, 是要被删除的【表】Class<?> genericType = service.getEntityClass();// eg: class com.guoqing.po.WechatUser// 知道要被删除的类型(PO)后, 就可以知道该 PO 被哪些表引用着log.info("【庆】{}", genericType.toString());return point.proceed();}}
二、SpringBoot 项目扫描类
🍀 ① 实现(implements)ApplicationContextAware 接口,并实现它的 void setApplicationContext(ApplicationContext)
方法
🎄 这是 Spring Bean 的生命周期方法
🎄 通过该方法可以获取 Spring 的 IoC 容器,进而获取到某个类的实例(通过它的getBean()
方法)
@Component
public class TestLifecycle implements ApplicationContextAware {private ApplicationContext iocContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext)throws BeansException {this.iocContext = applicationContext;UserController userController = (UserController) iocContext.getBean("Users");}
}
🍀 ② 实现(implements) InitializingBean 接口,并实现它的 void afterPropertiesSet()
方法
🎄 这是 Spring Bean 的生命周期方法
🎄 当实现该接口的类的属性被设置(注入)完毕后,afterPropertiesSet()
方法被调用
@Component
public class GForeignAspect implements ApplicationContextAware, InitializingBean {private ApplicationContext iocContext;// 属性被设置(注入)完毕时,InitializingBean 接口的 afterPropertiesSet 被调用@Autowired private ResourceLoader resourceLoader; @Overridepublic void setApplicationContext(ApplicationContext applicationContext)throws BeansException {this.iocContext = applicationContext; }@Overridepublic void afterPropertiesSet() throws Exception {}
}
(1) ResourceLoader 扫描类
🍀 Spring 框架的
org.springframework.core.io.ResourceLoader
类
@Slf4j
@Aspect
@Component
public class GForeignAspect implements InitializingBean {// 要被扫描的类的 class 文件private static final String SCAN_CLASS = "classpath*:com/guoqing/po/**/*.class";@Autowiredprivate ResourceLoader resourceLoader;/*** 扫描全部的 PO 类*/@Overridepublic void afterPropertiesSet() throws Exception {// 通过资源加载器拿到资源匹配解析器ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);// 通过资源加载器拿到元数据读取工厂类CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);// 通过资源匹配解析器读取到类的 class 资源Resource[] resources = resolver.getResources(SCAN_CLASS);if (resources.length == 0) {log.info("没有可供扫描的 PO");throw new Exception("没有可供扫描的 PO");}// 遍历 class 资源, 通过元数据解析器读取 class 资源的信息(如 类名)for (Resource resource : resources) {// 通过元数据读取工厂获取到元数据读取器MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);// 通过元数据读取器拿到 class 元数据读取器ClassMetadata classMetadata = metadataReader.getClassMetadata();// 通过元数据读取器拿到 class 的类名String className = classMetadata.getClassName();/*output:className = com.guoqing.po.PeopleclassName = com.guoqing.po.WechatUser*/System.out.println("className = " + className);}}
}
🎄 上面的一段代码都是比较固定的,直接复制使用即可
🎄 通过元数据读取器还可调用下面的方法获取其他 class 信息
🎄 上面的代码中,获取到了 class(或类)的完整路径。可通过 Java 的反射机制创建相应类的实例
(2) Map 的 computeIfAbsent 方法
- compute: 计算
- absent: 不存在
先看懂下面的代码,然后用 computeIfAbsent 改写下面的代码:
public class TestTest {@Testpublic void testComputeIfAbsent() {HashMap<String, Set<String>> hashMap = new HashMap<>();Set<String> set = new HashSet<>();set.add("杨天荣");hashMap.put("boy", set);// 判断 Map 中是否存在 key 是【boy】的键值对?if (hashMap.containsKey("boy")) {// 如果有, 获取该 key(boy)对应的 value(Set 类型)// 并往其中添加值【庆医】hashMap.get("boy").add("庆医");} else {// 如果没有, 新创建一个 Set, 把值【庆医】添加其中// 然后把新创建的这个 Set 添加到 Map 中Set<String> tmpSet = new HashSet<>();tmpSet.add("庆医");hashMap.put("boy", tmpSet);}// output: {boy=[杨天荣, 庆医]}System.out.println(hashMap.toString());}}
✏️ 上面代码的逻辑很容易,但是写起来比较麻烦
✏️ Map 提供了computeIfAbsent
方法,用以实现类型上面的逻辑功能,且写法很优美 🍀
public class TestTest {@Testpublic void testComputeIfAbsent() {HashMap<String, Set<String>> hashMap = new HashMap<>();HashSet<String> set = new HashSet<>();set.add("杨天荣");hashMap.put("boy", set);// hashMap.computeIfAbsent("boy", this::getSetInstance).add("庆医");hashMap.computeIfAbsent("boy", key -> getSetInstance(key)).add("庆医");// output: {boy=[杨天荣, 庆医]}System.out.println(hashMap.toString());}private Set<String> getSetInstance(String key) {return new HashSet<>();}}
🔋 computeIfAbsent: 如果存在映射的值,则返回该值,否则返回计算值
(3) 反射几个常用 api
① 创建一个测试注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyTestAnnotation {String function() default "该类作用显而易见, 不予解释";}
✏️ 当和反射结合的时候,注解的作用非常强大
✏️ 注解没有和反射结合的时候,注解毫无作用
✏️ 上面的代码是一个简单的注解案例,如需了解更多 💯 关于注解: https://zgqwillbeverylucky.blog.csdn.net/article/details/127098256
② 创建测试 PO 类
@Data
public class BasePo {private Integer id;private String name;private String createTime;}
@EqualsAndHashCode(callSuper = true)
@MyTestAnnotation(function = "人类, 用于构建人")
@Data
public class People extends BasePo {private String phone;private String job;}
③ 反射 api 获取指定类的指定注解信息
📝 已知 People 类的完整类名是:
com.guoqing.po.People
📝 已知 People 类有@MyTestAnnotation
注解
📝 获取出 People 类的@MyTestAnnotation
注解信息
public class TestReflection {private static final String CLASS_FULL_NAME = "com.guoqing.po.People";@Testpublic void test() throws ClassNotFoundException {// 使用 Class 类的 forName 静态方法, 传入完整类名, 创建该类的【类对象】Class<?> clsObj = Class.forName(CLASS_FULL_NAME);// 通过【类对象】的 getAnnotation 方法获取注解信息MyTestAnnotation annotation = clsObj.getAnnotation(MyTestAnnotation.class);// annotation = @com.guoqing.common.aop.foreign.annotation.MyTestAnnotation(function=人类, 用于构建人)System.out.println("annotation = " + annotation);// annotation.function = 人类, 用于构建人System.out.println("annotation.function = " + annotation.function());}
}
(4) 返回第一个不为空的字符串
public class GCommonUtil {/*** 判断一个字符串是否为 null 或空串*/public static boolean isEmptyStr(String string) {return string == null || "".equals(string);}/*** 传入多个字符串 (可以是可变参数, 或数组), 返回第一个不为空的字符串*/public static String firstNotEmptyStr(String... strings) {if (strings == null || strings.length < 1) return null;if (strings.length == 1) return strings[0];for (String string : strings) {if (!isEmptyStr(string)) {return string;}}return null;}}
(5) 判断一个【字符】是大写字母还是小写字母
public class GCommonUtil {/*** 当一个字符是【大】写英文字母的时候返回 true*/public static boolean isBigLetter(char source) {return source >= 'A' && source <= 'Z';}/*** 当一个字符是【小】写英文字母的时候返回 true*/public static boolean isSmallLetter(char source) {return source >= 'a' && source <= 'z';}}
(6) 让英文单词的首字母变小写
大写英文字符(如 A、E、F、B)加上数字 32 后变为小写英文字符
public class GCommonUtil {// 大写英文字符加上数字 32 后变为小写英文字符private static final int DELTA = 'a' - 'A'; // 32/*** 传入一个字符串, 若它的首字母是小写, 通过它的首字母创建 StringBuilder 对象返回* 若它的首字母是大写, 把首字母转换为小写后通过首字母创建 StringBuilder 对象返回*/public static StringBuilder firstLetterLowerStringBuilder(String source) {StringBuilder sb = new StringBuilder();if (isEmptyStr(source)) return sb;// 取出字符串的首字母char firstLetter = source.charAt(0);if (isBigLetter(firstLetter)) { // 如果首字母是大写的sb.append((char) (firstLetter + DELTA));} else {sb.append(firstLetter);}return sb;} /*** 返回英文字符串的首字母小写形式* 【 BOY-> bOY】*/public static String firstLetterLowercase(String source) {if (isEmptyStr(source)) return source;StringBuilder sb = firstLetterLowerStringBuilder(source);int length = source.length();for (int i = 1; i < length; i++) {sb.append(source.charAt(i));}return sb.toString();} }
(7) 驼峰转下划线形式
/*** 驼峰转下划线形式* LoveYou -> love_you*/public static String camel2underline(String source) {if (isEmptyStr(source)) return null;StringBuilder sb = firstLetterLowerStringBuilder(source);int len = source.length();for (int i = 1; i < len; i++) {char curChar = source.charAt(i);if (isBigLetter(curChar)) {sb.append("_");sb.append((char) (curChar + DELTA));} else {sb.append(curChar);}}return sb.toString();}
(8) GForeignTableInfo(外键表信息)
✏️ 该类用以描述类和表的信息
✏️ 该类的内容很多,该节先介绍一部分(后面慢慢补充)
🍀① cacheClassTableMap 该属性缓存某个表的 class 对象和外键表(GForeignTableInfo)信息。它是 static 属性(常量
static final
),所以它的 JVM 中只占用独一无二的一份内存
🍀 ② clsObj 该属性记录类对象(class)信息。它作为 key,和对应的 GForeignTableInfo 相映射
🍀③ tableName 该属性记录了该外键表信息对应的表的名字
@Getter
@Setter
public class GForeignTableInfo {// 缓存【类】和【表】的映射关系private static final Map<Class<?>, GForeignTableInfo> CACHE_CLASS_TABLE_MAP = new HashMap<>();private Class<?> clsObj;private String tableName;public static GForeignTableInfo getInfo(Class<?> clsObj, boolean newIfAbsent) {if (!newIfAbsent) return CACHE_CLASS_TABLE_MAP.get(clsObj);return CACHE_CLASS_TABLE_MAP.computeIfAbsent(clsObj, k -> {GForeignTableInfo foreignTableInfo = new GForeignTableInfo();foreignTableInfo.setClsObj(clsObj);// 设置表名String tableName;// 获取 clsObj 的 @GForeignTable 注解信息GForeignTable annotation = clsObj.getAnnotation(GForeignTable.class);if (annotation != null) {// 获取 @GForeignTable 注解中 name 或 value 注解信息// name 或 value 注解信息都可以表示表名tableName = GCommonUtil.firstNotEmptyStr(annotation.name(), annotation.value());} else {String clsSimpleName = clsObj.getSimpleName();tableName = GCommonUtil.firstLetterLowercase(clsSimpleName);}foreignTableInfo.setTableName(tableName);return foreignTableInfo;});}}
(9) 遍历 Class 对象的全部属性
相关文章:

数据一致性
目录一、AOP 动态代理切入方法(1) Aspect Oriented Programming(2) 切入点表达式二、SpringBoot 项目扫描类(1) ResourceLoader 扫描类(2) Map 的 computeIfAbsent 方法(3) 反射几个常用 api① 创建一个测试注解② 创建测试 PO 类③ 反射 api 获取指定类的指定注解信息(4) 返回…...

Docker不做虚拟化内核,对.NET有什么影响?
引子前两天刷抖音,看见了这样一个问题。问题:容器化不做虚拟内核,会有什么弊端?Java很多方法会跟CPU的核数有关,这个时候调用系统函数,读到的是宿主机信息,而不是我们限制资源的大小。思考&…...

HTML总结
CSS代码风格 空格规范: 1. 属性值前面,冒号后面,保留一个空格; 2. 选择器(标签)和大括号中间保留空格。 基本语法概述: 1.HTML标签是由尖括号包围的关键词,如<html> 2.HTM…...

ByteHouse:基于ClickHouse的实时数仓能力升级解读
更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 ByteHouse是火山引擎上的一款云原生数据仓库,为用户带来极速分析体验,能够支撑实时数据分析和海量数据离线分析。便捷的弹性扩缩容能力&…...

[SSD固态硬盘技术 15] FTL映射表的神秘面纱
为什么需要映射表?固态硬盘的存储器件采用的是闪存[5],具有以下几个特点: (1)读写基本单位是以页(Page)为单位,擦除是以块(Block)为单位。...

浅析依赖注入框架的生命周期(以 InversifyJS 为例)
在上一篇介绍了 VSCode 的依赖注入设计,并且实现了一个简单的 IOC 框架。但是距离成为一个生产环境可用的框架还差的很远。 行业内已经有许多非常优秀的开源 IOC 框架,它们划分了更为清晰地模块来应对复杂情况下依赖注入运行的正确性。 这里我将以 Inv…...

HER2靶向药物研发进展-销售数据-上市药品前景分析
HER2长期作为肿瘤领域的热门靶点之一,其原因是它在多部位、多种形式的癌症中均有异常的表达,据研究表明HER2除了在胃癌、胆道癌、胆管癌、乳腺癌、卵巢癌、结肠癌、膀胱癌、肺癌、子宫颈癌、子宫浆液性子宫内膜癌、头颈癌、食道癌中的异常表达还存在于多…...

【第38天】不同路径数问题 | 网格 dp 入门
本文已收录于专栏🌸《Java入门一百例》🌸学习指引序、专栏前言一、网格模型二、【例题1】1、题目描述2、解题思路3、模板代码4、代码解析5.原题链接三、【例题2】1、题目描述2、解题思路3、模板代码4、代码解析5.原题链接三、推荐专栏四、课后习题序、专…...

LINUX之链接命令
链接命令学习目标能够说出软链接的创建方式能够说出硬链接的创建方式1. 链接命令的介绍链接命令是创建链接文件,链接文件分为:软链接硬链接命令说明ln -s创建软链接ln创建硬链接2. 软链接类似于Windows下的快捷方式,当一个源文件的目录层级比较深&#x…...

1628_MIT 6.828 xv6_chapter0操作系统接口
全部学习汇总: GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 这本书最初看名字以为是对早期unix的一个解读,但是看了开篇发现 不完全是,只是针对JOS教学OS系统来做的一些讲解。 Xv6是对UNIX v6的重新实…...

使用 Sahi 实现 Web 自动化测试
Sahi 是 Tyto Software 旗下的一个基于业务的开源 Web 应用自动化测试工具。Sahi 运行为一个代理服务器,并通过注入 JavaScript 来访问 Web 页面中的元素。Sahi 支持 HTTPS 并且独立于 Web 站点,简单小巧却功能强大。它相对于 Selenium 等自动化测试工具…...

天津菲图尼克科技携洁净及无菌防护服解决方案与您相约2023生物发酵展
BIO CHINA 生物发酵产业一年一度行业盛会,由中国生物发酵产业协会主办,上海信世展览服务有限公司承办,2023第10届国际生物发酵产品与技术装备展览会(济南)于2023年3月30-4月1日在山东国际会展中心(济南市槐…...

Java 网络编程详解
1、什么是网络编程 在网络通信协议下,不同计算机上运行的程序,可以进行数据传输。 应用场景: 1、即时通信 2、网游对战 3、邮件等等 Java中可以使用java.net包下的技术轻松开发出常见的网络应用程序 2、网络编程三要素 2.1 IP地址 要…...

Scratch少儿编程案例-几何形式贪吃蛇
专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...

一定要收藏的面试思维导图,粉丝分享面试经验
一位粉丝分享面试经验:1.常见面试题有哪些?主要从以下一些知识点做了准备: 常用的分析方法、Excel、SQL、 A/B测试、产品分析。然后每份面试针对职位要求,还有前期和HR聊天一点点了解这个职位之后,定向准备。 Excel、S…...

【博客615】通过systemd设置cgroup来限制服务资源争抢
通过systemd设置cgroup来限制服务资源争抢 1、场景 我们的宿主机上通常会用systemctl来管理一些agent服务,此时我们需要限制服务的cpu,memory等资源用量,以防止服务之前互相争抢资源,导致某些核心agent运行异常 2、systemd与cgro…...

C语言经典编程题100例(21-40)
21、练习3-2 计算符号函数的值对于任一整数n,符号函数sign(n)的定义如下:请编写程序计算该函数对任一输入整数的值。输入格式:输入在一行中给出整数n。输出格式:在一行中按照格式“sign(n) 函数值”输出该整数n对应的函数值。输入样例1:10输出样例1:sig…...

Rabbitmq业务难点
Rabbitmq业务难点1.消息生产者发送的消息无法路由到任何一个队列怎么处理?2.聊聊Rabbitmq的七种工作模式3.Rabbitmq的消息确认机制4.Rabbitmq的消息持久化5.发布确认模式如何确保生产者能够成功将消息投递到消息队列6. Rabbitmq基于队列设置消息过期时间和单独针对消息设置过期…...

服务器如何下载百度网盘文件?Linux服务器如何在百度网盘中连接、上传下载;在Linux服务器上下载百度云盘中的资料
前言 百度云提供Python包bypy进行远程服务器的对接然后下载: https://github.com/houtianze/bypy 可以通过pip直接下载,授权本人的百度云账号后,就可以直接使Linux电脑本地文件与百度网盘的apps(我的应用数据)/bypy目…...

Cesium-数字仿真-你总要了解
Cesium(专注于时空数据的实时可视化) cesium是一款三维地球开源框架(可以多平台、跨平台使用)cesium隶属于美国AGI公司(Analytical Graphics Incorporation),美国通用公司宇航部的工程师创始开源 周边产…...

原型、原型链、__proto__与prototype的区别、继承
一.什么是原型与原型链 根据MDN官方解释: JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象[[Prototype]] ,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类…...

前端 面经
1说一说cookie sessionStorage localStorage 区别?解题思路得分点 数据存储位置、生命周期、存储大小、写入方式、数据共享、发送请求时是否携带、应用场景 标准回答 Cookie、SessionStorage、 LocalStorage都是浏览器的本地存储。 它们的共同点:都是存储…...

[oeasy]python0080_设置RGB颜色_24bit_24位真彩色_颜色设置
RGB颜色 回忆上次内容 上次 首先了解了 索引颜色 \33[38;5;XXXm 设置 前景为索引色\33[48;5;XXXm 设置 背景为索引色 RGB每种颜色 可选0-5总共 6 级 想用 精确RGB值 真实地 大红色画个 大红桃心 ♥️ 有可能吗??🤔 rgb 模式 关于 RGB 模式…...

实战项目-用户评论数据情绪分析
目录1、基于词典的方法2、基于词袋或 Word2Vec 的方法2.1 词袋模型2.2 Word2Vec3、案例:用户评论情绪分析3.1 数据读取3.2 语料库分词处理3.3 Word2Vec 处理3.4 训练情绪分类模型3.5 对评论数据进行情绪判断目的:去判断一段文本、评论的情绪偏向在这里&a…...

day02 DOS(续)文本编辑快捷键 发展史
day02课堂笔记 1、常用的DOS命令(续) 1.1、del命令,删除一个或者多个文件 删除T1.class文件 C:\Users\Administrator>del T1.class 删除所有.class结尾的文件,支持模糊匹配 C:\Users\Administrator>del *.class T1.classT1…...

arm64与aarch64
结论: 目前arm64和aarch64概念已合并,新版64位arm程序统称aarch64. 问题引入: 存在部分机器,安装arm版本ss,会报错,提示 rootlocalhost ~]# rpm -ivh senseshiel50 59130arm64.rpm Verifying... ########…...

QString详解
QString存储16位Qchar(Unicode)字符串 QString使用隐式共享(copy-on-write)来提高性能。 什么是Unicode? unicode是一种国际标准,支持当今使用的大多数操作系统,他是US-ASCII和Latin-1的超集(与子集相同字符编码相同…...

SpringCloud微服务
一、微服务架构 1.1、单体应用架构 将项目所有模块(功能)打成jar或者war,然后部署一个进程 优点: 1:部署简单:由于是完整的结构体,可以直接部署在一个服务器上即可。 2:技术单一:项目不需要复杂的技术栈,往往一套熟悉的技术栈就可以完成开…...

Hive 连接及使用
1. 连接 有三种方式连接 hive: cli:直接输入 bin/hive 就可以进入 clihiveserver2、beelinewebui 1.1 hiveserver2/beeline 1、开启 hiveserver2 服务 // 前台运行,当 beeline 输入命令时,服务端会返回 OK [roothadoop1 bin]…...

android libavb深入解读
1、vbmeta结构解析 2、 libavb代码解读 代码地址https://cs.android.com/android/platform/superproject/+/master:external/avb/libavb/ 解析参考AVB源码学习(四):AVB2.0-libavb库介绍1_摸肚子的小胖子的博客-CSDN博客 这篇blog将会更加深入,掌握avb流程。 2.1、avb_slot_…...