Spring AOP初步理解

前言:这是在慕课网上学习剑指Java面试-Offer直通车时所做的笔记,主要供本人复习之用.

目录

第一章 AOP的由来与简介

1.1 AOP的三种织入方式

1.2 AOP的主要名词概念

1.3 通知的类型

第二章 使用方法

2.1 在@Pointcut上写明切点,在@before等注解中将切点引入

2.2 直接在@before注解中将切点写明

第三章 实例

第四章 AOP的实现方法

4.1 代理模式

4.2 Spring里的代理模式的实现


第一章 AOP的由来与简介

软件工程有个基本的原则叫做关注点分离,通俗的理解就是不同的问题交给不同的部分去解决.每部分专注于解决自己的问题,面向切面编程AOP就是关注点分离的技术.

我们的代码是为了实现某个特定的业务逻辑,但是我们的代码往往不能专注于特定的业务逻辑,除了逻辑还要写事务缓存日志等等通用化的功能,为了将通用化的功能与业务功能分离开来,就出现了AOP技术.通用化功能代码的实现,对应的就是所谓的切面.

业务功能和切面代码分开后,架构后变得高内聚低耦合.

为了确保功能的完整性,切面最终需要被合并到业务中(Weave).

1.1 AOP的三种织入方式

第一第二种都需要特殊的java编辑器,第三种虽然需要特殊的开销但是只用编写代码就能完成,所以Spring采用的是第三种.

1.2 AOP的主要名词概念

Aspect:通用功能的代码实现(比如日志,事务等功能)

Target:目标对象,要被织入前面的对象,如一些controller对象.

Join Point: 可以切入的点,所有方法都可以作为切入的点.

Pointcut:定义通知应该切入到什么地方,负责具体定义Aspect被应用在哪些JoinPoint中.切入点的定义可以使用正则表达式.

Advice:是一个通知,切面是一个类,Advice就是类里的方法,以及方法如何织入到目标方法的方式.

Weaving:将切面应用到实际对象,从而创建一个新的代理对象的过程.对于Spring来说就是初始化context对象时完成织入操作.

1.3 通知的类型

 

第二章 使用方法

引入依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

切点位置的配置规则:

2.1 在@Pointcut上写明切点,在@before等注解中将切点引入

@Pointcut("execution(* com.example.TestAOP.service.DemoMethodService.*(..))")
    public void webLog(){log.info("这是weblog");}
//webLog当作标记使用
    @Before("webLog()")
    public void before(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        log.info("before方法执行"+method.getName());
    }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.2 直接在@before注解中将切点写明

@Before("execution(* com.example.TestAOP.service.DemoMethodService.*(..))")
    public void after(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        log.info("before方法执行"+method.getName());
    }

 

第三章 实例

切面代码:

@Aspect
@Component
@Slf4j
public class LogAspect {
    //方法一
    @Pointcut("execution(* com.example.TestAOP.service.DemoMethodService.*(..))")
    public void webLog(){log.info("这是weblog");}

    @Before("webLog()")
    public void before(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        log.info("before方法执行"+method.getName());
    }
    //方法二
    @After("execution(* com.example.TestAOP.service.DemoMethodService.*(..))")
    public void after(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        log.info("after方法执行");
    }

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

代码:

@RequestMapping("/testException")
    public String testException(){
        log.info("执行testException方法");
        try{
            testThrow();
        }catch (Exception e){
            log.info(e.toString());
            log.info("捕捉到了方法");
        }
        log.info("testException方法结束");
        return "testException方法结束";
    }

    public String testThrow(){
        int i=3/0;
        return "123";
    }

 

运行对应代码后的输出:

 

第四章 AOP的实现方法

Spring提供了两种方式来生成代理对象JdkProxy与Cglib(Code generation library),具体由哪种方式生成,由AdvisedSupport对象的配置来决定,默认的策略是如果目标类是接口,则用JDKProxy来实现,否则使用后者.

JDKProxy动态代理由反射来接收被代理的类,并且要求被代理的类必须实现一个接口,JDKProxy的核心是InvocationHandler接口和Proxy类,如果没有实现接口就会用Cglib.

Cglib是一个代码生成的类库,可以在运行时动态的生成某个类的子类,通过字节码来实现代理,Cglib通过继承的方式实现动态代理,所以如果类被定义为final,是无法用Cglib的.Cglib结局ASM实现,是一个操作字节码的框架.

反射机制在生成类的过程中比较高效,ASM在生成类之后的执行过程中比较高效.

4.1 代理模式

代理模式:接口+真实实现类+代理类

接口:

实现类(待被代理): 

代理类:

运行:

可以看到,pay方法被进行了增强,输出如下

 

4.2 Spring里的代理模式的实现

真实实现类的逻辑包含在了getBean方法里,getBean方法返回的实际上是Proxy实例.Proxy实例是采用JDKProxy或CGLIB动态生成的,

打开doGetBean方法,找到initializeBean,点进去

可以看到其执行了如下方法,再点进去

看到如下,再点进去.

看到如下接口,BeanPostProcessor接口实际上是由AbstractAutoProxyCreator类实现的.我们点进AbstractAutoProxyCreator类.

AbstractAutoProxyCreator类,在这里我们可以看到其实现的postProcessAfterInitialization方法,点进wrapIfNecessary方法,

可以看到其createProxy方法,再点进去.

可以看到getProxy方法,再点进去.

可以看到createAopProxy方法,再点进去.

可以看到getAopProxyFactory,由于getAopProxyFactory是一个接口,所以我们直接看ProxyCreatorSupport,我们点进去.往上拉,我们发现其默认是用DefaultAopProxyFactory实现的.再点进去

看到其createAopProxy方法.可以其不是返回JdkDynamicAopProxy就是返回ObjenesisCglibAopProxy.可以看到如果有接口,就返回JdkDynamicAopProxy否则返回Cglib.

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值