天天看点

自定义注解(spring)

终于有时间可以在这里写一篇博文了,今天写一下我在项目中用到的自定义注解,就是在每次操作项目的时候,想把它的操作加在我的数据库中,简单地说就是日志管理,这些东西都写完之后,我就问我自己,问什么要自定义注解写,而不是什么模式(代理模式,装饰器模式…),原始代码等等,一下子楞了,于是学习了这个东西,今天就在这里总结一下。。。

编程思想:垂直化编程,就是A—B---C—D…等执行下去,一个逻辑一个逻辑完了再执行下一个,但是spring 中AOP提供了一种思想,它的作用就是,当在业务不知情的情况下,对业务代码的功能的增强,这种思想使用的场景,例如事务提交、方法执行之前的权限检测、日志打印、方法调用事件等等。

就利用我的日志管理来述说一下这个AOP思想下的自定义注解是如何来实现的。。。

java在我们要自定义注解的时候提供了它自己的自定义语法以及元注解,元注解(负责注解其他注解): Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:

    [email protected],

    [email protected],

    [email protected],

    [email protected]

  这些类型和它们所支持的类在java.lang.annotation包中可以找到。

  [email protected]:用户描述注解的作用范围

  取值(ElementType)有:

    1.CONSTRUCTOR:用于描述构造器

    2.FIELD:用于描述域

    3.LOCAL_VARIABLE:用于描述局部变量

    4.METHOD:用于描述方法

    5.PACKAGE:用于描述包

    6.PARAMETER:用于描述参数

    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

[email protected]:表示需要在什么级别保存该注释信息

取值(RetentionPoicy)有:

    1.SOURCE:在源文件中有效(即源文件保留)

    2.CLASS:在class文件中有效(即class保留)

    3.RUNTIME:在运行时有效(即运行时保留)(常用)

  [email protected]:Documented是一个标记注解

  [email protected] :用于声明一个注解;

自定义注解语法:

public @interface 注解名 {定义体}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {

    String value() default "";
}
  
           

注意:

1.只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为default默认类型

2.这里的参数成员可以是八种基本数据类型,和String,Enum,Class,annotations等数据类型,以及这一些类型的数组,这里是String

3.最好把参数名称设为"value()" 后面为默认的值。

/**
 * 系统日志,切面处理类
 * 
 * @author stm
 * @email [email protected]
 * @date 2017年11月21日
 */
@Aspect
@Component
public class SysLogAspect {

	@Autowired
	private LogService logService;
	//这个里面需要写自定义注解的全限定名(包名+类名)
	@Pointcut("@annotation(com.stm.controller.base.annotation.SysLog)")
	public void logPointCut() { 
		
	}

	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		long beginTime = System.currentTimeMillis();
		//执行方法
		Object result = point.proceed();
		//执行时长(毫秒)
		long time = System.currentTimeMillis() - beginTime;
		//保存日志
		saveSysLog(point, time);
		return result;
	}

	/**
	 * 保存系统日志
	 * @param joinPoint
	 * @param time
	 */
	private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {

		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		/*SysLog syslog = method.getAnnotation(SysLog.class);
		if(syslog != null){
			//注解上的描述
			System.out.println(syslog.value());
		}*/
		/*SysLog sysLog = new ();*/
//获取request请求
		ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
		HttpServletRequest request = attr.getRequest();

		UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
		Browser browser = userAgent.getBrowser();
		String browsers = browser+"";
		System.out.println("浏览器    "+browsers);
		OperatingSystem os = userAgent.getOperatingSystem();
		String oss = os+"";
		System.out.println("os  "+oss);
		String ip = "";
		try {
			ip = InetAddress.getLocalHost().getHostAddress(); //ip 地址
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		System.out.println("ip   "+ip);
		Date date = new Date();
		System.out.println(date);
		com.stm.pojo.system.SysLog  sysLog  =  new com.stm.pojo.system.SysLog();
		SysLog syslog = method.getAnnotation(SysLog.class);
		HttpSession session = request.getSession();
		String userName = (String) session.getAttribute("userName");
		if(syslog != null){
			//注解上的描述
			sysLog.setLogIp(ip);
			sysLog.setLogRemark(syslog.value());
			sysLog.setLogTime(date);
			sysLog.setUserName(userName);
			sysLog.setLogSystem(oss);
			sysLog.setLogBrowser(browsers);
		}
		//请求的方法名
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = signature.getName();
		//sysLog.setMethod(className + "." + methodName + "()");
		logService.insert(sysLog);
	}
}
           

如何使用?

例如在用户登录的时候需要把相关的 信息添加到数据库中,这个时候就需要在登录成功之后在跳转到列表的时候添加注解:

@SysLog("用户登录")
	 @RequestMapping("/main/index")
	    public String index(){
	        return "main/index";
	    }
           

而这个注解中写的(“用户登录”)就是添加自定义时候的默认值的value()相对应的值。。。

对了这里需要配置aop以及依赖

<!-- aop 注解实现 -->  
<aop:aspectj-autoproxy/>  
           
<!-- AspectJ -->  
<dependency>  
    <groupId>org.aspectj</groupId>  
    <artifactId>aspectjrt</artifactId>  
    <version>1.6.10</version>  
</dependency>  
<dependency>  
    <groupId>org.aspectj</groupId>  
    <artifactId>aspectjweaver</artifactId>  
    <version>1.7.2</version>  
</dependency>  
           

今天就到这里,之后会更详细的整理!!!