本来打算自己跟了源码后整理成博客,发现有的地方没弄懂,然后去网上找资料,看到一个写的很好的博客,就放弃了自己详细写。
做一个总结:
首先明白三个概念
1.pointcut :切入点 指明了对某个类的某个方法切入
2.advice 通知,分为前置,后置,环绕,异常,返回前 等五类通知,指明了 在某个时机干某事。
3.advisor pointcut+advice :指明了在某个地方的某个时机干某个事情。
spring在初始化IOC容器的时候,就会解析pointcut,advice生成对应的beanDefinition。
spring是在那个地方为bean创建的代理呢?
在bean初始化完后有个处理所有后置通知的逻辑
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor extends BeanPostProcessor
aop的处理逻辑类就是AbstractAutoProxyCreator,因为这个类也间接实现了BeanPostProcessor,所有这个类的postProcessAfterInitialization也会被调用
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//看这个方法实现
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && 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.
//如果有代理逻辑
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建了代理对象
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;
}
表面上的逻辑就是这个样子,当然,spring肯定还多了很多的处理
比如:为bean方法寻找合适的通知器(根据pointcut定义的规则,按照类和方法匹配)
生成拦截器链(一个方法可能有多个advise,spring将多个advise封装成拦截器链)
生成代理对象,加入了advise的逻辑
<aop:aspectj-autoproxy proxy-target-class=“true”/>
roxy-target-class:默认为false,接口用jdk代理,其它用cglib代理
设置为true时,强制采用cglib代理
<aop:aspectj-autoproxy expose-proxy=“true” />
expose-proxy:默认为false,为true时会将代理对象放到ThreadLocal中
比如TestService中有两个方法 A(),B() ,A调用B中的方法this.B(),这样B方法是没有经过代理的
要是想调用代理后的B(),就应该 ((TestService) AopContext.currentProxy()).B();
要了解AOP的整个代理实现逻辑:
可以看这三篇博客
https://www.imooc.com/article/43378
https://www.imooc.com/article/43379
https://www.imooc.com/article/43380