Spring AOP相关内容及其应用实现

一:一些概念

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

猜你喜欢

转载自blog.csdn.net/lihongtai/article/details/82528593