Spring注解解析及工作原理、自定义注解

在这里插入图片描述
注解(Annotation) 提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析注解来使用这些 数据),用来将任何的信息或者元数据与程序元素(类、方法、成员变量等)进行关联。其实就是更加直观更加明了的说明,这些说明信息与程序业务逻辑没有关 系,并且是供指定的工具或框架使用的。Annotation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的申明语句中。

Annotation其实是一种接口。通过java的反射机制相关的API来访问Annotation信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。Java语言解释器在工作时会忽略这些Annotation,因此在JVM中这些Annotation是“不起作用”的,只能通过配套的工具才能对这些Annotation类型的信息进行访问和处理。

Annotation和interface的异同:

1、 annotition的类型使用关键字@interface而不是interface。它继承了java.lang.annotition.Annotition接口,并非申明了一个interface。

2、 Annotation类型、方法定义是独特的、受限制的。Annotation类型的方法必须申明为无参数、无异常抛出的。这些方法定义了Annotation的成员:方法名称为了成员名,而方法返回值称为了成员的类型。而方法返回值必须为primitive类型、Class类型、枚举类型、Annotation类型或者由前面类型之一作为元素的一位数组。方法的后面可以使用default和一个默认数值来申明成员的默认值,null不能作为成员的默认值,这与我们在非Annotation类型中定义方法有很大不同。Annotation类型和他的方法不能使用Annotation类型的参数,成员不能是generic。只有返回值类型是Class的方法可以在Annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。

3、 Annotation类型又与接口有着近似之处。它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。

自定义注解

AOP思想下的自定义注解
java在我们要自定义注解的时候提供了它自己的自定义语法以及元注解,元注解(负责注解其他注解): Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
    1.@Target,
    2.@Retention,
    3.@Documented,
    4.@Inherited
  这些类型和它们所支持的类在java.lang.annotation包中可以找到。
  1.@Target:用户描述注解的作用范围
  取值(ElementType)有:
    1.CONSTRUCTOR:用于描述构造器
    2.FIELD:用于描述域
    3.LOCAL_VARIABLE:用于描述局部变量
    4.METHOD:用于描述方法
    5.PACKAGE:用于描述包
    6.PARAMETER:用于描述参数
    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
2.@Retention:表示需要在什么级别保存该注释信息
取值(RetentionPoicy)有:
    1.SOURCE:在源文件中有效(即源文件保留)
    2.CLASS:在class文件中有效(即class保留)
    3.RUNTIME:在运行时有效(即运行时保留)(常用)
  3.@Documented:Documented是一个标记注解
  4.@Inherited :用于声明一个注解;
自定义注解语法:
public @interface 注解名 {定义体}

/**
* @author LittleOrange
* @version 2018年12月10日 下午4:59:15
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Component
public @interface SysLog {

	String value() default "";
}

注意:
1.只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为default默认类型
2.这里的参数成员可以是八种基本数据类型,和String,Enum,Class,annotations等数据类型,以及这一些类型的数组,这里是String
3.最好把参数名称设为"value()" 后面为默认的值。

/**
 * 系统日志,切面处理类
 * @author LittleOrange
 * @version 2018年12月10日 下午4:59:15
 */
@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);
	}
}

注解本身不做任何事情,只是像xml文件一样起到配置作用。注解代表的是某种业务意义,注解背后处理器的工作原理如上所示:首先解析所有属性,判断属性上是否存在指定注解,如果存在则根据搜索规则取得bean,然后利用反射原理注入。如果标注在字段上面,也可以通过字段的反射技术取得注解,根据搜索规则取得bean,然后利用反射技术注入。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Security允许我们通过自定义注解来标记方法或类,以便在授权过程中使用。下面是一个简单的示例: 1. 创建一个自定义注解: ```java @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface CustomPermission { String value() default ""; } ``` 2. 在Spring Security配置类中,创建一个方法,用于解析自定义注解并应用相应的权限逻辑: ```java @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { // ...其他配置... @Override protected MethodSecurityExpressionHandler createExpressionHandler() { DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator()); return expressionHandler; } } ``` 3. 创建一个自定义的 PermissionEvaluator 实现类,用于处理自定义注解中的权限逻辑: ```java @Component public class CustomPermissionEvaluator implements PermissionEvaluator { @Override public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { if (authentication == null || !authentication.isAuthenticated()) { return false; } if (!(permission instanceof String)) { return false; } // 在这里根据需要实现自定义的权限逻辑 return false; } @Override public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { // 该方法可用于处理非领域对象的权限逻辑,根据需要实现 return false; } } ``` 4. 在需要授权的方法或类上使用自定义注解: ```java @RestController public class MyController { @CustomPermission("customPermissionValue") @GetMapping("/secured") public String securedMethod() { return "Hello, secured!"; } } ``` 通过以上步骤,我们可以使用自定义注解`@CustomPermission`来标记需要授权的方法或类,并在`CustomPermissionEvaluator`中实现具体的权限逻辑。然后,Spring Security会在授权过程中使用我们自定义的注解和权限逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值