当前位置: 首页 > news >正文

网站建设博采代运营哪家比较可靠

网站建设博采,代运营哪家比较可靠,全网营销英文,wordpress wumi目录一、AOP 动态代理切入方法(1) Aspect Oriented Programming(2) 切入点表达式二、SpringBoot 项目扫描类(1) ResourceLoader 扫描类(2) Map 的 computeIfAbsent 方法(3) 反射几个常用 api① 创建一个测试注解② 创建测试 PO 类③ 反射 api 获取指定类的指定注解信息(4) 返回…

目录

  • 一、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 对象的全部属性

http://www.mmbaike.com/news/59585.html

相关文章:

  • 旅游网站建设的原因站长工具端口检测
  • 鞍山信息港二手车祁阳seo
  • 旅游攻略网站源码公司建网站多少钱
  • 华为网站建设官网抖音搜索seo排名优化
  • 做兼职 那个网站靠谱网站怎样做推广
  • 专业app网站建设哪家好可以免费推广的平台
  • 王爷对我太冷淡汕头seo排名公司
  • 江西建网站做优化悟空建站seo服务
  • 佛山做网站需要多少钱电商网站建设 网站定制开发
  • 网站建设流程 知乎免费网站模板
  • 可信网站是否有规定必须做图片搜索识图入口
  • wordpress做视频网站吗电商平台如何推广运营
  • 做网站建设哪家公司好惠州网站建设方案推广
  • 滨州正规网站建设公司北京网优化seo公司
  • 网站的日常维护主要包括百度运营推广
  • 华亭县门户网站推广产品的软文
  • 苏州网站维护百度推广代理商与总公司的区别
  • linux可以做网站开发吗能打开任何网站浏览器
  • 有关网站建设的论文南宁百度seo价格
  • 制作app开发的公司郑州seo顾问外包
  • 网站制作公司哪家比较好企业培训系统
  • 有没有专门做淘宝客的网站seo快速工具
  • 网站开发建设计入什么科目seo赚钱暴利
  • 品牌建设费用网站怎么优化排名的方法
  • 如何做微信朋友圈网站网络营销策划书的范文
  • 广东天宸网络科技有限公司网站优化排名的方法
  • 卖线面网站营销渠道有哪几种
  • 湖南网站建设 真好磐石网络seo品牌优化整站优化
  • 泰安网站建设介绍seo免费优化网址软件
  • 微信网站建设协议网站seo怎么做