Aop切面编程,是基于ioc实现的,spring 容器工厂,通过ioc(控制反转),大大的简化的程序开发难度,用户不用在手动进行new 来创建对象了,降低了程序的耦合度,spring 容器,通过 1. 注解 ,2.set get方法,3 构造函数的方式,将对象注入到spring的bean中,用户完全不用关系bean的生命周期,都直接交给spring进行管理,spring 通过cglib进行动态代理,aop也即是在spring的代理执行前后,进行aop的方法调用。
实现原理
Java之JDK和CGlib实现动态代理-yellowcong
aop的实现,可以基于 cglib 和jdk proxy .
-
cglib asm
cglib实现代理,被代理的对象不需要实现接口 ,底层是通过asm来进行字节码的修改,asm是一套字节码修改框架,性能更高。 -
jdk proxy
这个是jdk本地实现的代理方式,这种实现方式,被代理的对象需要实现接口
aop案例
0 代码地址
https://gitee.com/yellowcong/springboot-demo/tree/master/springboot-annotaion-aop
目录结构
1. 创建注解
首先,我们创建一个注解 ,这个类名为LogInfo , 用于记录日志使用 , 这个注解注入点是ElementType.METHOD
package com.yellowcong.anno;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 代码创建: yellowcong <br/>
* 创建日期: 2019年3月29日 <br/>
* 功能描述: 定义注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogInfo {
/**
* 操作描述
*
* @return {String}
*/
String value() default "";
/**
* 操作类型: 类型
*
* @return {String}
*/
String type() default "";
}
2. 创建Aop类
aop的切面创建,需要通过@Aspect 这个注解进行注释,表示俺是一个切面,@Around
表示在这个方法前后执行,注入注解对象 @annotation(logInfo) ,表示,俺遇到这个注解就会 织入这个切面。
package com.yellowcong.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.yellowcong.anno.LogInfo;
/**
* @author fangliang
* @since 2019/03/08 11:26
*/
@Aspect
@Component
public class ApiLogAspect {
public static final Logger NUM = LoggerFactory.getLogger("num");
/**
* 代码创建: yellowcong <br/>
* 创建日期: 2019年3月29日 <br/>
* 功能描述: 这个地方需要注意 @annotation(logInfo) 中的logInfo 和函数 LogInfo logInfo 必须相同,不然就会报错
* @param point
* @param logInfo
* @return
* @throws Throwable
*/
@Around("@annotation(logInfo)")
public Object around(ProceedingJoinPoint point, LogInfo logInfo) throws Throwable{
long begin = System.currentTimeMillis();
Object result = point.proceed();
//执行时间
long period = System.currentTimeMillis() - begin;
System.out.println(logInfo.type()+":"+logInfo.value());
//记录日志
NUM.info("花费时间{},注解参数{}:{}",period,logInfo.value(),logInfo.type());
return result;
}
}
3. 测试使用
在这个服务中,我只是使用了 @LogInfo(value=“test”,type=“yellowcong_type”) 注解,然后,这个切面就完事了,我们访问这个链接的时候,就会调用我们的aop的方法了。
package com.yellowcong.controller;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.yellowcong.anno.LogInfo;
@Controller
@EnableAutoConfiguration
@RequestMapping("/sample")
public class SampleController {
/**
* 代码创建: yellowcong <br/>
* 创建日期: 2019年3月29日 <br/>
* 功能描述: 使用了loginfo的注解
* @return
*/
@RequestMapping("/home")
@ResponseBody
@LogInfo(value="test",type="yellowcong_type")
String home() {
return "Hello yellowcong!";
}
}
4. 执行结果
参考文章
https://www.cnblogs.com/hujunzheng/p/6255463.html
https://blog.csdn.net/hjl21/article/details/80924809