互联网架构-Spring5.0源码深度解析-023:SpringBean的Aop源码分析

1 SpringAOP源码分析课前疑问

课题内容:

  1. SpringAop注解底层实现原理
  2. SpringAop与Bean的生命周期关系
  3. Spring的Bean对象是如何初始化的
  4. SpringAop底层到底是用cglib还是JDk动态代理

2 SpringBean的生命周期终极版本01

SpringBean的生命周期

  1. 进入到刷新的方法refresh();
  2. finishBeanFactoryInitialization() 初始化所有单例对象;
  3. beanFactory.preInstantiateSingletons();初始化所有非懒加载的单例对象;
  4. getBean->doGetBean() 先查询该对象是否有初始化过,没有的话就创建注册到IOC容器中;
  5. createBean()创建对象,判断对象如果是单例的情况下调用该方法;
  6. doCreateBean()创建IOC对象;
  7. createBeanInstance使用java的反射技术实例化对象;
  8. populateBean给对象set方法属性赋值;
  9. invokeAwareMethods 判断bean的类型是否有ware相关依赖,如果存在的情况下回调方法;
  10. initializeBean执行初始化的方法(也可以自定义初始化的方法)
  11. applyBeanPostProcessorsBeforeInitialization在初始化方法之前执行处理(增强)
  12. invokeInitMethods调用自定义init方法(使用java的反射技术)
  13. applyBeanPostProcessorsAfterInitialization在初始化方法之后执行处理(增强)
  14. 正常使用注册的bean对象
  15. 销毁bean

3 SpringBean的生命周期终极版本02

Bean对象到底是如何创建的?
反射机制。

@Component
public class OrderService5 implements InitializingBean {
    public OrderService5(){
        System.out.println("1.无参构造函数");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("2.执行自定义bean的init方法");
    }
}

运行结果:
在这里插入图片描述
AbstractAutowireCapableBeanFactory类中,先createBeanInstance使用java的反射技术实例化对象,再initializeBean执行初始化的方法

4 @EnableAspectJAutoProxy源码分析01

SpringAop源码分析 需要关联SpringBean的生命周期
思考:
1.什么时候创建代理类对象
2.SpringAOP中如何综合运用cglib和Jdk动态代理

@EnableAspectJAutoProxy源码分析
1.@EnableAspectJAutoProxy 开启Aop权限
2.@Import(AspectJAutoProxyRegistrar.class)
3.AspectJAutoProxyRegistrar 手动注册 切面类
4.AnnotationAwareAspectJAutoProxyCreator 需要将该类注册的IOC容器中
5.注册bean信息内容:
Beanid:org.springframework.aop.config.internalAutoProxyCreator
class:AnnotationAwareAspectJAutoProxyCreator
了解SpringAOP底层是如何实现的,离不开AnnotationAwareAspectJAutoProxyCreator
在这里插入图片描述
验证注入AnnotationAwareAspectJAutoProxyCreator

@Configuration
@ComponentScan(basePackages = {"com.mayikt.service","com.mayikt.aop"})
@EnableAspectJAutoProxy
public class MyConfig {
}
public class AppLogin {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String s : beanDefinitionNames) {
            System.out.println("beanDefinitionNames:" + s);
        }
        AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator = applicationContext.getBean("org.springframework.aop.config.internalAutoProxyCreator", AnnotationAwareAspectJAutoProxyCreator.class);
        System.out.println(annotationAwareAspectJAutoProxyCreator.getClass());

    }
}

运行结果:
在这里插入图片描述

5 @EnableAspectJAutoProxy源码分析02

在这里插入图片描述
由类图关系可知, AnnotationAwareAspectJAutoProxyCreator是BeanPostProcessors子类。
BeanPostProcessors 是对bean的初始化方法实现增强(Init方法之前和之后处理)
AnnotationAwareAspectJAutoProxyCreator 本质其实就是对init方法实现增强。
思考:AnnotationAwareAspectJAutoProxyCreator 前置和后置到底在做什么事情?
在类AbstractAutoProxyCreator中
前置:不会处理任何的事情
后置:postProcessAfterInitialization使用后置处理实现代理对象的创建

6 @EnableAspectJAutoProxy源码分析03

在这里插入图片描述
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// 有具体前置业务逻辑处理
}
// 没有具体业务逻辑的
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}

7 @EnableAspectJAutoProxy源码分析04

任何bean对象在初始化之前都会调用AbstractAutoProxyCreator后置处理判断是否需要创建代理类对象在这里插入图片描述

8 @EnableAspectJAutoProxy源码分析05

public interface MemberService {
    public String login(String userName, String passWord);
}
@Component
public class MemberServiceImpl  implements  InitializingBean,MemberService {
    public MemberServiceImpl() {
        System.out.println("1无参构造函数....");
    }

    @Override
    public String login(String userName, String passWord) {
        int i = 1 / 0;
        System.out.println(">>>>正在执行登陆业务逻辑>>>>> userName:" + userName + "passWord:" + passWord);
        return ">>>>登陆业务逻辑..<<<<";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("2执行自定义bean的init方法");
    }
}
@Component
public class PayService {

    public void pay() {
        System.out.println("pay");
    }
}
@Aspect
@Component
public class LoginAop {
    //Aspect 定义切点类

    /**
     * @Pointcut 定义切入点
     */
//    @Pointcut(value = "execution (* com.mayikt.service.*..*.*(..))")
    @Pointcut("execution (* com.mayikt.service..*.*(..))")
    public void loginAop() {
    }
    //@Pointcut(value = "execution (* com.mayikt.service.*..*.*(..))")  service.所有子包 下面所有的类所有的方案

    /**
     * 前置通知
     *
     * @param joinPoint
     */
    @Before("loginAop()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println(">>>>>>>前置通知<<<<<<<<<<< ");
    }

    /**
     * 后置通知
     */
    @After("loginAop()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println(">>>>>>>>后置通知<<<<<<<<<");
    }

    /**
     * 环绕通知
     *
     * @param joinPoint
     */
    @Around("loginAop()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println(">>>>环绕通知之前执行...>>>>>>");
        joinPoint.proceed();// 执行目标方案
        System.out.println(">>>>环绕通知之后执行...>>>>>>");
    }

    /**
     * 运行通知
     */
    @AfterReturning("loginAop()")
    public void afterReturning(JoinPoint joinPoint) {
        System.out.println("运行通知执行.....");
    }

    /**
     * 异常通知
     *
     * @param joinPoint
     */
    @AfterThrowing("loginAop()")
    public void afterThrowing(JoinPoint joinPoint) {
        System.out.println(">>>>>异常通知");
    }
}
public class AppLogin {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        MemberService memberService = applicationContext.getBean("memberServiceImpl", MemberService.class);
        memberService.login("zhangsan","11");

        PayService payService = applicationContext.getBean("payService", PayService.class);
        payService.pay();
    }
}

断点调试Aop创建代理类对象:
在这里插入图片描述
在这里插入图片描述
创建代理对象,如果被代理的这个类如果实现了接口的话,也就使用JDK动态代理,如果没有实现接口则使用cglib。
注意:只要是一个接口都可以
疑问:aop中存在很多通知的,每个通知最终如何形成链执行。底层For循环

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值