springAop和AspectJ的关系
Aop是一种概念,springAop、AspectJ都是Aop的实现,SpringAop有自己的语法,但是语法复杂,所以SpringAop借助了AspectJ的注解,但是底层实现还是自己的。
springAop支持AspectJ
1、启用@AspectJ支持
要使用Java @Configuration启用@AspectJ支持,请添加@EnableAspectJAutoProxy注释,proxyTargetClass属性默认是false,表示使用jdk动态代理,如果设为true,则使用cglib动态代理。
@Configuration
@ComponentScan("org.su")
@EnableAspectJAutoProxy
public class AppConfig {
}
2、声明一个Aspect
申明一个@Aspect注释类,并且定义成一个bean交给Spring管理。
@Component
@org.aspectj.lang.annotation.Aspect
public class LogAspect {
@Pointcut("@annotation(com.su.springcode.annotation.Log)")
public void logPointCut(){
}
@Around("logPointCut()")
public void aroundAdvice(ProceedingJoinPoint jointPoint){
try {
jointPoint.proceed();
//获取方法参数值
Object[] args = jointPoint.getArgs();
//根据方法请求参数值,获取方法的url
String url = "";
if(args!=null && args.length>0){
for (Object arg : args) {
if(arg instanceof Request){
url = ((Request) arg).getValue();
break;
}
}
}
Signature signature = jointPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
Log log = method.getAnnotation(Log.class);
System.out.println(log.type());
System.out.println(url);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
切入点表达式由@Pointcut注释表示。这边定义了加了@Log注解的所有方法为一个切入点,并在这个切入点定义了一个环绕通知@Around
3、自定义注解@Log
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
String type();
}
4、定义一个Dao
@Repository
public class UserDao {
@Autowired
UserService userService;
@Log(type = "查询")
public void query(Request request){
System.out.println("userDao query...");
}
@Log(type = "更新")
public void update(Request request){
System.out.println("userDao update...");
}
}
请求信息对象Request:
public enum Request {
DATA("数据层"),
Service("业务层");
private String value;
Request(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
5`、定义测试类
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
UserDao userDao = context.getBean(UserDao.class);
userDao.query(Request.DATA);
userDao.update(Request.DATA);
}
}
启动测试: