1. 创建拦截的Bean
@Configuration
@Import(value=LogAspect.class)
@EnableAspectJAutoProxy
public class MathCalculator {
public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
}
@SuppressWarnings("resource")
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MathCalculator.class);
MathCalculator mathCalculator = ac.getBean(MathCalculator.class);
mathCalculator.div(1, 2);
}
}
2. 创建Advisor
@Aspect
public class LogAspect {
//抽取公共的切入点表达式
//1、本类引用
//2、其他的切面引用
@Pointcut("execution(* com.gz.MathCalculator.*(..))")
public void pointCut(){};
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
}
@After("com.gz.LogAspect.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
跟踪@EnableAspectJAutoProxy注解
根据@EnableAspectJAutoProxy注解可知,该注解@Import(AspectJAutoProxyRegistrar.class)给容器中导入AspectJAutoProxyRegistrar。利用AspectJAutoProxyRegistrar自定义给容器中注册bean;
跟踪代码,最终注入AnnotationAwareAspectJAutoProxyCreator类。
AnnotationAwareAspectJAutoProxyCreator类图
从上边的类图关系我们发现两个重要的接口BeanFactoryAware和SmartInstantiationAwareBeanPostProcessor接口。
在AbstractAdvisorAutoProxyCreator类中setBeanFactory(BeanFactory beanFactory)方法上打上断点跟踪代码,如下:。
我们先了解Spring实例化对象具体步骤如下:
传入配置类、创建IOC容器
注册配置类,调用refresh()刷新容器
registerBeanPostProcesors(beanFactory)注册bean的后置处理器来拦截bean的创建
3.1. 先获取IOC容器已经定义的需要创建对象的所有BeanPostProcessor
3.2. 给容器中加别的BeanPostProcessor
3.3. 优先注册了PriorityOrdered接口的BeanPostProcessor
3.4. 再给容器中注册了Ordered接口的BeanPostProcessor
3.5. 注册没有实现优先级接口的BeanPostProcessor
3.6. 注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存到容器中创建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】
3.6.1. 创建Bean的实例
3.6.2. populateBean,给Bean各种属性赋值
3.6.3. initializeBean,初始化Bean
3.6.3.1. invokeAwareMethods(),处理Aware接口的方法回调
3.6.3.2. applyBeanPostProcessorsBeforeInitialization(),执行后置处理器的postProcessBeforeInitialization()方法
3.6.3.3. invokeInitMethods(),执行初始化方法
3.6.3.4. applyBeanPostProcessorsAfterInitialization(),执行后置处理器的postProcessAfterInitialization()方法
finishBeanFactoryInitialization(),完成BeanFactory初始化工作,完成剩下的单例Bean
4.1. 遍历获取容器中所有的Bean,依次创建对象getBean(beanName); getBean()->doGetBean()-> getSingleton()
4.2. 创建Bean
4.2.1. 先从缓存中获取Bean,如果能获取,说明之前创建过,直接返回,否则创建。
4.2.2. createBean ();创建Bean
4.2.2.1. resolveBeforeInstantiation(beanName,mbdToUse);解析BeforeInstantia
希望后置处理器在此能返回一个代理对象,如果能返回代理对象就使用,否则继续
4.2.2.1.1. 如果是InstantiationAwareBeanPostProcessor后置处理器
后置处理器尝试创建代理Bean
4.2.2.2. doCreateBean(beanName, mbdToUse, args)和3.6的步骤一样
关于Spring后置处理器:
根据类的继承关系我们知道AnnotationAwareAspectJAutoProxyCreator继承自InstantiationAwareBeanPostProcessor,根据以上流程4.2我们知道在每一个Bean创建之前,调用postProcessBeaforeInstantiation()。
在AbstractAutoProxyCreator类中postProcessBeforeInstantiation(Class> beanClass, String beanName)方法上打上断点跟踪代码,如下:
初始化前(postProcessBeforeInstantiation)
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
// 判断当前Bean是否在advisedBeans中,(保存了所有需要增强的Bean)
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 判断当前Bean是否是基础类型||是否需要跳过
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
AbstractAutoProxyCreator.postProcessBeforeInstantiation()方法
1.1. 判断当前Bean是否在advisedBeans中,(保存了所有需要增强的Bean)
1.2. 判断当前Bean是否是基础类型,Advice、Pointcut、Advisor、AopInfrastructureBean或者是不是切面(@Aspect)
1.3. 是否需要跳过
1.3.1. 是否是候选的增强器(切面里面的通知方法),判断每一个增强器是否是AspectJPointcutAdvisor类型,是返回true,否则false【每一个封装的通知方法的增强器是InstantiationModelAwarePointcutAdvisor】
1.3.2. 永远返回false
初始化后(postProcessAfterInitialization)
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 获取当前bean的所有增强器(如果采用的是BeanNameAutoProxyCreator类处理,此时不会获取Advisor,
会在createProxy方法中获取,
具体看createProxy方法中的buildAdvisors(beanName, specificInterceptors);)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 保存当前bean在advisedBeans中
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 如果当前Bean需要增强器,创建当前Bean代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果当前Bean需要增强器,创建当前Bean代理对象
protected Object createProxy(
Class> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this); // copy代理配置,如proxyTargetClass,exposeProxy等
if (!proxyFactory.isProxyTargetClass()) {// false -> jdk代理;true -> cglib代理
// 再次确认是否要代理类对象
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 不需要则获取其代理接口集合
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);// 增强器(通知方法)
proxyFactory.setTargetSource(targetSource);// 目标类
customizeProxyFactory(proxyFactory);// 是否冻结,及继续往里面加Advisor(通知方法)
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
创建对象,调用postProcessAfterInitialization()
2.1. 获取当前bean的所有增强器(通知方法)
2.1.1. 找到候选的所有的增强器
2.1.2. 获取到能在bean中使用的增强器
2.1.3. 对找到的增强器排序
2.2. 保存当前bean在advisedBeans中
2.3. 如果当前Bean需要增强器,创建当前Bean代理对象
2.3.1. 获取所有增强器(通知方法)
2.3.2. 保存到ProxyFactory
2.3.3. 创建代理对象,Spring自动决定
2.3.3.1. JdkDynamicAopProxy jdk动态代理
2.3.3.2. ObjenesisCglibAopProxy cglib动态代理
目标方法执行
容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息
3.1. CglibAopProxy.intercept();拦截目标方法的执行
3.2. 根据ProxyFactory获取执行将要执行的拦截器链
3.2.1. List interceptorList保存所有的拦截器
3.2.2. 遍历所有的增强器,将其转化为Interceptor;
3.2.3. 将增强器转化List;如果是MethodInterceptor,直接放到结合中,
如果不是,使用AdvisorAdapter转化为MethodInterceptor,
3.3. 如果没有拦截器链,直接执行目标方法
3.4. 如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个CglibMethodInvocation对象,返回结果