...
一:一些概念
1.什么是Spring AOP:
面向对象编程(OOP)是一种自上而下的逻辑实现,也就是一种主业务逻辑的实现,但是在这些主业务逻辑之间会有一些和和主业务逻辑无关,但是又非常重要的一些内容需要实现,比如权限的校验,日志的记录,效率检查(就是验证一些方法的从开始到结束需要的执行时间),这些实现散落在代码的各个角落,Spring AOP就是把这些散落的代码集中起来的一种解决方案
2.Spring AOP的两种代理方式: JDK代理和CGLib代理
@EnableAspectJAutoProxy(proxyTargetClass = false) //默认接口类是走JDK代理
如果proxyTargetClass = true ,则接口类也会走CGLib代理
3.从JDK动态代理底层分析,JDK动态代理类只能支持接口类的原因:
JDK动态代理生成 的动态代理类的方式为 public class $Proxy extends Proxy implements 接口类,
因为Java是单继承的,所以JDK动态代理只能为接口类作代理
4.Spring AOP 和 AspectJ的关系:Spring AOP是程序要达到的目标,AspectJ是实现这个目标的一种手段
5.IOC 和 DI 的关系: IOC是需要达到的目标,DI是实现这个目标的手段,一种实现IOC的方式
6.ProceedingJoinPoint 和 JoinPoint 的关系:ProceedingJoinPoint extends JoinPoint
ProceedingJoinPoint用于环绕通知,可以动态修改方法参数
二:实现一个AOP实例步骤
1.创建Maven项目 添加jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
2.创建AppConfig
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Configuration //表示这个文件是一个配置文件
@ComponentScan("com.roger")//配置注解扫描的范围
@EnableAspectJAutoProxy//启动AspectJ注解
public class AppConfig {
}
|
3.创建一个接口测试类
public interface IndexDao {
void query();
}
|
import com.roger.dao.IndexDao;
import org.springframework.stereotype.Service;
@Service
//注意如果时接口实现类,注解是@Service
//如果是类的话使用注解 @Component
//在接口实现类上使用注解@Component不起作用
public class IndexDaoImpl implements IndexDao {
@Override
public void query() {
System.out.println("beign exe the business ....");
}
}
|
4.创建测试类,即可执行接口的方法了
import com.roger.config.AppConfig;
import com.roger.dao.IndexDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestAop {
public static void main(String[] args) {
AnnotationConfigApplicationContext annoConfigAppContext = new AnnotationConfigApplicationContext(AppConfig.class);//注解启动加载器
IndexDao indexDao = annoConfigAppContext.getBean(IndexDao.class);
indexDao.query();
}
}
|
此时执行结果为:
beign exe the business ....
如果想在这个执行结果的前后,记录一些相关信息,则需要引入AOP,即面向切面编程的思想
5.创建一个切面
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component//这里一定要把切面交给Spring管理,添加注解@Component
public class MyAspect {
//配置切入点,是连接点的集合
@Pointcut("execution(* com.roger.dao..*.*(..))")
//这里问什么创建一个方法,因为注解需要一个载体,
//这个方法没有任何实际意义
public void pointCutWithExecution() {
}
//声明通知,即这个方法在连接点的什么时候执行
@After("com.roger.config.aspect.MyAspect.pointCutWithExecution()")
public void after() {
System.out.printf("after the method ");
}
@Around("com.roger.config.aspect.MyAspect.pointCutWithExecution()")
public Object around(ProceedingJoinPoint proceedJoinPoint) throws Throwable {
System.out.println("before exe method....");
Object[] realArgs = new Object[proceedJoinPoint.getArgs().length];
Object[] args = proceedJoinPoint.getArgs();
int i = 0 ;
for(Object arg : args){
arg = arg + " ang Mary";
realArgs[i++] = arg;
}
Object obj = proceedJoinPoint.proceed(realArgs);
}
}
|
此时运行测试类,执行结果为:
before exe method....
beign exe the business ....//真正的方法执行内容
after the method
github地址:https://github.com/LiHongTai/aop-study.git