023:SpringBean的Aop源码分析
1 SpringAOP源码分析课前疑问
课题内容:
- SpringAop注解底层实现原理
- SpringAop与Bean的生命周期关系
- Spring的Bean对象是如何初始化的
- SpringAop底层到底是用cglib还是JDk动态代理
2 SpringBean的生命周期终极版本01
SpringBean的生命周期
- 进入到刷新的方法refresh();
- finishBeanFactoryInitialization() 初始化所有单例对象;
- beanFactory.preInstantiateSingletons();初始化所有非懒加载的单例对象;
- getBean->doGetBean() 先查询该对象是否有初始化过,没有的话就创建注册到IOC容器中;
- createBean()创建对象,判断对象如果是单例的情况下调用该方法;
- doCreateBean()创建IOC对象;
- createBeanInstance使用java的反射技术实例化对象;
- populateBean给对象set方法属性赋值;
- invokeAwareMethods 判断bean的类型是否有ware相关依赖,如果存在的情况下回调方法;
- initializeBean执行初始化的方法(也可以自定义初始化的方法)
- applyBeanPostProcessorsBeforeInitialization在初始化方法之前执行处理(增强)
- invokeInitMethods调用自定义init方法(使用java的反射技术)
- applyBeanPostProcessorsAfterInitialization在初始化方法之后执行处理(增强)
- 正常使用注册的bean对象
- 销毁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循环