自定义注解实现A0P的权限控制

自定义注解实现A0P的权限控制

精选文章moguli202025-04-25 13:37:4611A+A-

第一篇-自定义注解+A0P基本知识

1.注解概念

注解是一种能被添加到java代码中的元数据,类、方法、变量、参数和包都可以用注解来修饰。注解对于它所修饰的代码并没有直接的影响。

即:

注解是一种元数据形式。即注解是属于java的一种数据类型,和类、接口、数组、枚举类似。
注解用来修饰,类、方法、变量、参数、包。
注解不会对所修饰的代码产生直接的影响。

2 为什么要使用注解

在注解之前,XML被广泛用于元数据。但是随着项目中代码量的增大,XML维护变得越来越麻烦。开发人员希望元数据与代码是紧密耦合,而XML与代码之间的耦合非常松散。

1、假设您要设置一些应用程序范围内的常量。在这种情况下,XML是一个更好的选择,因为它与任何特定的代码段都不相关。

2、如果要将某个方法作为服务公开,则注解将是一个更好的选择,因为它需要与该方法紧密结合

现在,大多数框架都将XML和注解结合使用,以充分利用两者的积极方面。

3 注解的工作方式

注解仅仅是元数据,不包括任何业务逻辑。那它的使用者是谁呢?像@Override这种注解,JVM是它的使用者,它在字节码级别工作。如果我们自己编写了一个注解,那我们就要去实现它的消费者,否则,我们自定义的注解是没有任何作用的。

4 编写自定义注解

在编写自定义注解的时候,我们首先需要搞清楚几个默认的注解,这几个注解仅仅作用与另一个注解之上。

@Documented

注解表明这个注解要被javadoc记录。注解默认状态下是不被javadoc记录的。

@Retention

注解表明该注解保留到那个阶段,主要有三个值:

SOURCE —— 这种注解保留在源代码级别,编译时就会被忽略

CLASS —— 这种注解编译时被保留,在class文件中存在,但JVM将会忽略

RUNTIME —— 这种注解将被JVM保留,利用反射机制可以获取并使用。

@Target

t注解表明该注解作用的范围。包括package、method、field、构造方法、成员变量、枚举值等属性。

@Inherited

注解表明该注解是否影响子类。如果定义的注解上使用了@Inherited标记,则使用该注解的某个父类,它的子类默认继承所有的属性

5 案例需求

使用自定义注解+aop 完成dao层的拦截控制,比如我们要拦截删除和修改的方法,并把信息用日志的方式存到文件中

5.1环境搭建

创建Java项目,结构如下

5.2 创建自定义注解

@Target(ElementType.METHOD)//注解的作用目标是:方法
@Retention(RetentionPolicy.RUNTIME) //注解可以在运行时通过反射获取到
public @interface MyAnn {
String value() default "";
}

5.3创建切面类

package com.bobo.aop;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
@Aspect //标注为切面类
@Component //标注为ioc管理
public class MyAop {
//配置环绕通知,记录删除和修改的日志数据
//@annotation 固定写法
//com.bw.aop.MyAnn 自定义注解的全路径名
@Around(value = "@annotation(com.bw.aop.MyAnn)")
public void log1(ProceedingJoinPoint pjp) throws Throwable {
//获取日志对象
Logger logger = Logger.getLogger(MyAop.class);
//获取方法名和参数
Object proceed = pjp.proceed();
if (proceed != null) { //目标方法执行成功,则记录日志
String name = pjp.getSignature().getName();//目标方法参数
Object[] args = pjp.getArgs();//目标方法参数
String argsStr = Arrays.toString(args);
logger.info("在这个时间:" + new Date() + "执行了:" + name + "方法,传递的参数:" + argsStr);
}
}
}

5.4dao 层接口

5.5 dao实现类

5.6 log4j.proerties

#日志级别debug<info<warn<error
log4j.rootLogger=INFO, Console ,File 
#输出到控制台
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#输出到文件# org.apache.log4j.FileAppender
#File
log4j.appender.File =org.apache.log4j.DailyRollingFileAppender 
log4j.appender.File.File = c://class/log.log
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =%d [%t] %-5p [%c] - %m%n

5.7测试

public class UserTest {
UserService service;
@Before //在执行UserTest 类中其他方法时,该方法先执行
public void init(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
service = context.getBean(UserService.class);
}
@Test
public void deleteById() {
service.deleteById(2);
}
@Test
public void update() {
User user = service.get(4);
user.setName("八戒");
service.update(user);
}
}

5.7效果

5.7.1控制台打印

5.7.2 日志文件

6小结

自定义注解+aop的步骤:

1.开发自定义注解

2.开发aop,并在切点处使用自定义注解的全路径名

3.在目标方法上标注自定义注解

点击这里复制本文地址 以上内容由莫古技术网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

莫古技术网 © All Rights Reserved.  滇ICP备2024046894号-2