上代码:
注入一个Aop切面类:
package cn.cdulm.aspects;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
@Aspect // 标记为切面
@Component // 标记为Bean组件,进入Ioc容器,才能切入Bean
public class LogAspects {
@Pointcut("execution(* cn.cdulm.service.impl.*.*(..))")
public void pointcut() {
}
// 前置通知
@Before("pointcut()")
public void before() {
System.out.println("before - 前置通知");
}
// 后置通知
@After("pointcut()")
public void after() {
System.out.println("after - 后置通知");
}
// 后置异常通知
@AfterThrowing("pointcut()")
public void afterThrowing() {
System.out.println("afThrow - 后置异常通知");
}
// 后置返回通知
@AfterReturning("pointcut()")
public void afterReturning() {
System.out.println("return - 后置返回通知");
}
// 环绕通知
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) {
// 获取方法名
String methodName = joinPoint.getSignature().getName();
// 所有的参数
Object[] args = joinPoint.getArgs();
Object res = null;
try {
System.out.println("Around - 前置通知:" + methodName + " 方法执行,参数:" + Arrays.asList(args));
res = joinPoint.proceed();
System.out.println("Around - 后置通知:" + methodName + " 方法执行,参数:" + Arrays.asList(args));
} catch (Throwable e) {
System.out.println("Around - 异常通知:" + e);
} finally {
System.out.println("Around - 返回通知:" + res);
}
return res;
}
}
从execution(* cn.cdulm.service.impl.*.*(..)) 查看切入的包、类和方法:
可以发现切入的是cn.cdulm.service.impl包下所有的类及方法:
只有UserServiceImpl类:
package cn.cdulm.service.impl;
import cn.cdulm.dao.IUserDao;
import cn.cdulm.entity.User;
import cn.cdulm.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
@Autowired
IUserDao userDao;
@Override
public User select(Integer id) throws Exception {
System.out.println("查询");
// throw new RuntimeException("抛异常啦!");
return userDao.select(id);
}
@Override
public void add(User user) throws Exception {
System.out.println("添加");
userDao.add(user);
}
@Override
public void delete(Integer id) throws Exception {
System.out.println("删除");
userDao.delete(id);
}
@Override
public void update(User user) throws Exception {
System.out.println("更改");
userDao.update(user);
}
}
测试方法:
package cn.cdulm.test;
import cn.cdulm.entity.User;
import cn.cdulm.service.IUserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class IocTest {
@Test
public void f1() throws Exception {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("classpath:/springIoc.xml");
IUserService bean = ioc.getBean(IUserService.class);
// System.out.println(bean.getClass());
User s = bean.select(112);
// 没有使用切面结果:class cn.cdulm.service.impl.UserServiceImpl
/* 使用切面后结果:class com.sun.proxy.$Proxy20 jdk生成的动态代理类
当类实现了接口会默认由jdk的方式生成代理类
当类没有实现接口会默认由CGLIB的方式生成代理类
*/
}
}
输出结果:
Around - 前置通知:select 方法执行,参数:[112]
before - 前置通知
查询
return - 后置返回通知
after - 后置通知
Around - 后置通知:select 方法执行,参数:[112]
Around - 返回通知:cn.cdulm.entity.User@be35cd9
现在将UserServiceImpl中的异常注释打开:
运行结果:
Around - 前置通知:select 方法执行,参数:[112]
before - 前置通知
查询
afThrow - 后置异常通知
after - 后置通知
Around - 异常通知:java.lang.RuntimeException: 抛异常啦!
Around - 返回通知:null
由此可以看出@Around环绕通知是五大通知里面功能最全最强的。