天天看點

自定義注解(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>  
           

今天就到這裡,之後會更詳細的整理!!!