针对“spring中AOP 注解开发示例详解”的完整攻略,我将分为以下几个部分进行讲解:
1. AOP 概述
AOP,即 Aspect Oriented Programming,面向切面编程,是一种程序设计的思想,可以让程序逻辑分散到各个部分,从而增加代码的可维护性和辅助性。Spring框架提供了完善的AOP实现,可以通过纯Java编写切面代码,实现统一的业务逻辑。
2. AOP 注解详解
Spring框架的AOP机制有两种实现方式:一种是通过XML配置文件实现,另一种则是通过注解实现。其中,注解是更为常见的方式,比XML更加简洁明了,而且维护成本更低。下面是常用的AOP注解:
注解 | 描述 |
---|---|
@Aspect | 表明该类是一个切面,用于声明通知和切点 |
@Before | 在切点之前执行通知 |
@After | 在切点之后执行通知 |
@AfterReturning | 在切点方法返回后执行通知 |
@AfterThrowing | 在切点方法抛出异常后执行通知 |
@Around | 在切点前后都会执行的通知 |
3. AOP 注解示例一
首先,我们创建一个Calculator
接口,定义两个方法:加法和减法。
public interface Calculator {
int add(int a, int b);
int sub(int a, int b);
}
然后,创建一个实现类CalculatorImpl
,实现Calculator
接口。
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int sub(int a, int b) {
return a - b;
}
}
接下来,我们需要创建一个切面类LoggingAspect
,并且在这个类中添加@Aspect
注解。
@Aspect
@Component
public class LoggingAspect {
}
然后,我们需要在这个切面类中定义一个切点,通过@Pointcut
注解来定义。
@Pointcut("execution(* com.example.demo.Calculator.*(..))")
public void pointcut() {}
上面这个切点表示匹配Calculator接口下的所有方法。
接着,我们需要定义通知,并且通过@Before
注解实现前置通知。在LoggingAspect
类中实现如下方法:
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("执行方法 " + methodName + " 前,参数为:" + Arrays.toString(args));
}
最后,我们就可以在DemoApplication
中调用Calculator
的方法,观察是否有输出日志。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
Calculator calculator = new CalculatorImpl();
int result = calculator.add(1, 2);
System.out.println("1+2=" + result);
result = calculator.sub(3, 4);
System.out.println("3-4=" + result);
}
}
如果控制台输出如下内容,则说明实现成功。
执行方法 add 前,参数为:[1, 2]
1+2=3
执行方法 sub 前,参数为:[3, 4]
3-4=-1
4. AOP 注解示例二
现在,我们通过一个更加复杂的示例来观察AOP注解的用法。我们需要创建一个UserService
接口,并且定义两个方法:通过用户名查找用户和保存用户。
public interface UserService {
User getUser(String username);
void saveUser(User user);
}
其中,User
是一个模型类。
public class User {
private String username;
private String password;
// getter 和 setter 略
}
接下来,创建一个实现类UserServiceImpl
,实现UserService
接口并且添加@Component
注解。
@Service
public class UserServiceImpl implements UserService {
private Map<String, User> users = new HashMap<>();
@Override
public User getUser(String username) {
return users.get(username);
}
@Override
public void saveUser(User user) {
users.put(user.getUsername(), user);
}
}
然后,我们需要创建一个切面类UserServiceAspect
。
@Aspect
@Component
public class UserServiceAspect {
private final Logger logger = LoggerFactory.getLogger(UserServiceAspect.class);
@Before("execution(* com.example.demo.UserService.*(..)) && args(username, ..)")
public void before(String username) {
logger.info("[before]开始查找用户:{}", username);
}
@AfterReturning(value = "execution(* com.example.demo.UserService.*(..))", returning = "result")
public void after(User result) {
logger.info("[after]用户信息:{}", result);
}
@Around("execution(* com.example.demo.UserService.*(..)) && args(user, ..)")
public void around(ProceedingJoinPoint pjp, User user) throws Throwable {
if (user.getPassword().length() < 6) {
logger.error("[around]密码长度不能少于6个字符");
} else {
pjp.proceed();
}
}
}
我们来逐步分析这段代码。首先,在before
方法中,我们定义了一个前置通知,这个通知用于输出日志信息。@Before
注解中的execution()
表示匹配UserService
接口下所有方法,同时使用args()
来匹配参数是String
类型的方法,并且可以通过..
来表示任意参数。
接着,在after
方法中,我们定义了一个后置通知,这个通知用于输出用户信息。@AfterReturning
注解中的execution()
和args()
的含义与before
方法中相同,同时使用returning
属性来匹配返回值为User
类型的方法。
最后,在around
方法中,我们定义了一个环绕通知,这个通知用于校验密码长度。@Around
注解中的execution()
和args()
的含义与before
方法中相同,同时在方法体中,我们可以通过ProceedingJoinPoint
类和proceed()
方法来实现对方法的执行。如果密码长度小于6个字符,我们将输出错误日志,否则将继续执行方法。
最后,我们在DemoApplication
中调用UserService
中的方法,观察是否有输出日志。
@Service
public class DemoApplication implements CommandLineRunner {
@Autowired
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
User user1 = new User();
user1.setUsername("xiaoming");
user1.setPassword("123");
userService.saveUser(user1);
User user2 = new User();
user2.setUsername("xiaowang");
user2.setPassword("123456");
userService.saveUser(user2);
User user3 = userService.getUser("xiaoming");
User user4 = userService.getUser("xiaowang");
}
}
控制台输出如下内容,则说明实现成功。
[around]密码长度不能少于6个字符
[before]开始查找用户:xiaoming
[before]开始查找用户:xiaowang
[after]用户信息:User{username='xiaowang', password='123456'}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:spring中AOP 注解开发示例详解 - Python技术站