例子还是之前的例子。仍然是对mage进行法术攻击时的咒语进行校验,不过略微提高了扩展性。

应用示例

1、在.properties文件中定义参数格式(正则):

sp1=^\\D*hello\\D*$
sp2=^\\D*world\\D*$

2、对需要检查格式的方法参数进行注解,注解中传入的参数需要与.properties文件中的定义相对应:

package sample.spring.iocbasis.hero;

import sample.spring.iocbasis.annotation.CheckFormat;

public interface Mage {

    void attack(@CheckFormat("sp1") String sp1, @CheckFormat("sp2")String sp2);
}
package sample.spring.iocbasis.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface CheckFormat {
String value();
}

注解.java

3、定义切面:

package sample.spring.iocbasis.weapon;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import sample.spring.iocbasis.annotation.CheckFormat; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Parameter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern; public class MagicBook implements Weapon { private static final Logger LOGGER = LogManager.getLogger(); private static int count = 0; private int no = ++count; private static Map<String, Pattern> map = new HashMap<>(); static {
// 把.properties文件里的键值对读到内存里
Properties prop = new Properties();
String filename = "\\easy-validator.properties";
try (InputStream input = MagicBook.class.getClassLoader().getResourceAsStream(filename)){
if (input == null) {
throw new RuntimeException("Sorry, unable to find " + filename);
}
prop.load(input);
Enumeration<?> e = prop.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String value = prop.getProperty(key);
map.put(key, Pattern.compile(value));
}
} catch (IOException e) {
throw new RuntimeException("An exception occurred while reading " + filename, e);
}
} public void magicLimit(ProceedingJoinPoint jp) {
try {
LOGGER.info("{}试图发动一次魔法攻击,正在检查咒语格式 ...", jp.getThis());
// 获取参数对象以便获得注解值
MethodSignature signature = (MethodSignature) jp.getSignature();
Parameter[] parameters = signature.getMethod().getParameters();
// 获取参数值
Object[] args = jp.getArgs();
// 逐个参数进行判断
for (int i = 0; i != args.length; ++i) {
if (args[i] instanceof String) {
// 获取参数对应格式名(默认即为参数名)
String formatName = parameters[i].getAnnotation(CheckFormat.class).value();
String arg = (String) args[i];
// 非空检查
if (StringUtils.isBlank(arg)) {
LOGGER.info("{}不能为空!", formatName);
return;
} else {
Pattern pattern = map.get(formatName);
// 程序员要确保格式已经定义
if (pattern == null) throw new RuntimeException(formatName + "格式未定义");
// 格式检查
if (!pattern.matcher(arg).matches()) {
LOGGER.info("{}格式不正确!", formatName);
return;
}
}
}
}
// 所有字符串检查通过才放行
jp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
} @Override
public void attack() { } @Override
public String toString() {
return "MagicBook{" +
"no=" + no +
'}';
}
}

4、在IOC容器的配置文件中应用切面:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="magicBook" class="sample.spring.iocbasis.weapon.MagicBook"/> <aop:config>
<aop:aspect ref="magicBook">
<aop:pointcut id="mageAttack"
expression="execution(* sample.spring.iocbasis.hero.Mage.*(..))" />
<aop:around pointcut-ref="mageAttack" method="magicLimit" />
</aop:aspect>
</aop:config>
</beans>

5、测试切面:

package sample.spring.iocbasis;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import sample.spring.iocbasis.hero.Mage; public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("\\spring\\config.xml");
Mage mage = context.getBean("mage", Mage.class);
mage.attack("hello", "world.");
mage.attack("hlo", "worl.");
mage.attack("hello", " ");
}
}
/*
output=
MageImpl{no=1}试图发动一次魔法攻击,正在检查咒语格式 ...
MageImpl{no=1}用MagicBook{no=1}发起了一次攻击
MageImpl{no=1}试图发动一次魔法攻击,正在检查咒语格式 ...
sp1格式不正确!
MageImpl{no=1}试图发动一次魔法攻击,正在检查咒语格式 ...
sp2不能为空!
*/

Spring笔记 #02# 利用切面和注解校验方法参数的更多相关文章

  1. Spring笔记02(3种加载配置文件的方式)

    1.不使用Spring的实例: 01.Animal接口对应的代码: package cn.pb.dao; /** * 动物接口 */ public interface Animal { //吃饭 St ...

  2. Spring——原理解析-利用反射和注解模拟IoC的自动装配

    解析Spring的IoC容器基于注解实现的自动装配(自动注入依赖)的原理 1.本文案例 使用注解和反射机制来模拟Spring中IoC的自动装配功能 定义两个注解:@Component,用来标注组件:@ ...

  3. Spring原理解析-利用反射和注解模拟IoC的自动装配

  4. Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录

    http://my.oschina.net/ydsakyclguozi/blog/413822

  5. Spring中声明式事务的注解@Transactional的参数的总结(REQUIRED和REQUIRES_NEW的与主方法的回滚问题)

    一.事务的传播行为1.介绍 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行.2.属性 事务的传播行为可以由传 ...

  6. 【VB6笔记-02】从Command中获取链接参数

    Public Sub GetParameters() Dim Para As String Para = Command$() gstrUserID = GetCommandPara(Para, ) ...

  7. Spring笔记02_注解_IOC

    目录 Spring笔记02 1. Spring整合连接池 1.1 Spring整合C3P0 1.2 Spring整合DBCP 1.3 最终版 2. 基于注解的IOC配置 2.1 导包 2.2 配置文件 ...

  8. Spring 笔记1

    1.在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书<Expert one-on-one J2EE Design and Deve ...

  9. Spring中的@Valid 和 @Validated注解你用对了吗

    1.概述 本文我们将重点介绍Spring中 @Valid和@Validated注解的区别 . 验证用户输入是否正确是我们应用程序中的常见功能.Spring提供了@Valid和@Validated两个注 ...

随机推荐

  1. Android的Base64的坑

    Base64.encodeToString加密后一直和Apache的对不上,多了换行符,最后使用了NO_WRAP就好了 Base64.encodeToString(src, Base64.URL_SA ...

  2. java面试复习题四

    一.redis最大缓存和回收策略 二.常用的数据库Druid线程池的参数设置 三.Spring的几大特性和应用 参考 Spring的核心特性就是IOC和AOP,IOC(Inversion of Con ...

  3. 从0移植uboot(六) _实现网络功能

    为uboot添加网卡功能可以让uboot通过tftp下载内核, 方便我们的开发, 对于网卡功能的移植,我们依然在在一遍又一遍的实践这个uboot改造的套路. 找运行逻辑,即插入代码的位置. 根据运行逻 ...

  4. update条件判断更新

    UPDATE cw_party tp, cw_shop tsSET tp.state = 3, ts.bonus_average = CASEWHEN ts.bonus_average > 0 ...

  5. Solve Error: 'NSInvalidArgumentException', reason: '-[UITableView mas_makeConstraints:]: unrecognized selector sent to instance 0x7fa5c402fa00'

    下面是iOS开发用第三方库可能出现的错误,及其解决方法: 1. 'NSInvalidArgumentException', reason: '-[UITableView mas_makeConstra ...

  6. Luogu 1086 - 花生采摘 - [简单模拟]

    题目链接:https://www.luogu.org/problemnew/show/P1086 题目描述鲁宾逊先生有一只宠物猴,名叫多多.这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着 ...

  7. HotSpot虚拟机

    注:如其中有不懂的名词,下面有名词解释 1.对象的创建(限于普通Java对象,不包括数组和Class对象等) (1)检查这个指令的参数能否在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是 ...

  8. 作业二 分布式版本控制系统Git的安装与使用

    第一步:Git bash配置 修改用户名和邮箱地址: $ git config --global user.name "zzj" $ git config --global use ...

  9. POJ3461 Oulipo 字符串

    正解:kmp/哈希 解题报告: 传送门! 这题其实就kmp板子,,,用来复习下kmp的太久没打了QAQ 所以kmp做法就不港了放个代码就是了QAQ #include<algorithm> ...

  10. dict()的另一种用法

    先了解两个内容: 定义字典的两种方法: d1 = { ‘name’ :‘zzl’} #方法一 d2 = dict( name = 'zzl' ) #方法二 2. __dict__()方法不记录类的属性 ...