上一篇博客介绍了AOP的相关概念:白话Spring源码(九):Spring AOP原理和相关概念。其实AOP的原理比较简单,但是里面的概念和抽象比较多,入口也藏得比较深。好了,我带大家从入口开始进去源码吧!
要找到入口我们就必须搞清楚 Spring AOP 是在何处向目标 bean 中织入通知(Advice)的。也说过 Spring 是如何将 AOP 和 IOC 模块整合到一起的,即通过拓展点 BeanPostProcessor 接口。Spring AOP 抽象代理创建器实现了 BeanPostProcessor 接口,并在 bean 初始化后置处理过程中向 bean 中织入通知。下面我们就来看看相关源码,如下:
public abstract class AbstractAutoProxyCreator extends ProxyConfig
implements BeanPostProcessor, BeanFactoryAware, Ordered {
public Object postProcessBeforeInitialization(Object bean, String name) {
return bean;
}
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getInterceptorsAndAdvisorsForBean
*/
public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
// Check for special cases. We don't want to try to autoproxy a part of the autoproxying
// infrastructure, lest we get a stack overflow.
if (isInfrastructureClass(bean, name) || shouldSkip(bean, name)) {
logger.debug("Did not attempt to autoproxy infrastructure class '" + bean.getClass() + "'");
return bean;
}
TargetSource targetSource = getTargetSource(bean, name);
Object[] specificInterceptors = getInterceptorsAndAdvisorsForBean(bean, name);
// proxy if we have advice or if a TargetSourceCreator wants to do some
// fancy stuff such as pooling
if (specificInterceptors != DO_NOT_PROXY || !(targetSource instanceof SingletonTargetSource)) {
// handle prototypes correctly
Advisor[] commonInterceptors = resolveInterceptorNames();
List allInterceptors = new ArrayList();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors != null) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isInfoEnabled()) {
int nrOfCommonInterceptors = commonInterceptors != null ? commonInterceptors.length : 0;
int nrOfSpecificInterceptors = specificInterceptors != null ? specificInterceptors.length : 0;
logger.info("Creating implicit proxy for bean '" + name + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
ProxyFactory proxyFactory = new ProxyFactory();
// copy our properties (proxyTargetClass) inherited from ProxyConfig
proxyFactory.copyFrom(this);
if (!getProxyTargetClass()) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class[] targetsInterfaces = AopUtils.getAllInterfaces(bean);
for (int i = 0; i < targetsInterfaces.length; i++) {
proxyFactory.addInterface(targetsInterfaces[i]);
}
}
for (Iterator it = allInterceptors.iterator(); it.hasNext();) {
Advisor advisor = GlobalAdvisorAdapterRegistry.getInstance().wrap(it.next());
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(getTargetSource(bean, name));
return proxyFactory.getProxy();
}
else {
return bean;
}
}
}
这个类实现了BeanPostProcessor的接口,这个会在bean初始化前后调用:
createBean方法的部分代码:
bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);//执行初始化前执行的自定义方法
invokeInitMethods(bean, beanName, mergedBeanDefinition);//执行初始化方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);//执行初始化后执行的自定义方法
以上就是 Spring AOP 创建代理对象的入口方法分析,过程比较简单,这里简单总结一下:
- 若 bean 是 AOP 基础设施类型,则直接返回
- 为 bean 查找合适的通知器
- 如果通知器数组不为空,则为 bean 生成代理对象,并返回该对象
- 若数组为空,则返回原始 bean
这里有两个关键点
1.为bean查找合适的通知器。
2.为bean生成代理对象。
下面我们就围绕着两点展开,这篇博客主要分析怎么为bean找到合适的通知器,下面就是对应的调用:
Object[] specificInterceptors = getInterceptorsAndAdvisorsForBean(bean, name);
getInterceptorsAndAdvisorsForBean:这里没有具体的实现,只是调用findEligibleAdvisors,然后排序
protected Object[] getInterceptorsAndAdvisorsForBean(Object bean, String name) {
List advices = findEligibleAdvisors(bean.getClass());
if (advices.isEmpty()) {
return DO_NOT_PROXY;
}
advices = sortAdvisors(advices);
return advices.toArray();
}
findEligibleAdvisors:先找到所有的Advice,然后再筛选
protected List findEligibleAdvisors(Class clazz) {
List candidateAdvice = findCandidateAdvisors();
List eligibleAdvice = new LinkedList();
for (int i = 0; i < candidateAdvice.size(); i++) {
// Sun, give me generics, please!
Advisor candidate = (Advisor) candidateAdvice.get(i);
if (AopUtils.canApply(candidate, clazz, null)) {
eligibleAdvice.add(candidate);
logger.info("Candidate Advice [" + candidate + "] accepted for class [" + clazz.getName() + "]");
}
else {
logger.info("Candidate Advice [" + candidate + "] rejected for class [" + clazz.getName() + "]");
}
}
return eligibleAdvice;
}
findCandidateAdvisors:用beanFactory找到所有实现Advisor接口的类
protected List findCandidateAdvisors() {
if (!(getBeanFactory() instanceof ListableBeanFactory)) {
throw new IllegalStateException("Cannot use DefaultAdvisorAutoProxyCreator without a ListableBeanFactory");
}
ListableBeanFactory owningFactory = (ListableBeanFactory) getBeanFactory();
String[] adviceNames = BeanFactoryUtils.beanNamesIncludingAncestors(owningFactory, Advisor.class);
List candidateAdvisors = new LinkedList();
for (int i = 0; i < adviceNames.length; i++) {
String name = adviceNames[i];
if (!this.usePrefix || name.startsWith(this.advisorBeanNamePrefix)) {
Advisor advisor = (Advisor) owningFactory.getBean(name);
candidateAdvisors.add(advisor);
}
}
return candidateAdvisors;
}
那怎么筛选适合的Advice:
AopUtils.canApply(candidate, clazz, null)
canApply:判断是IntroductionAdvisor还是PointcutAdvisor
IntroductionAdvisor与PointcutAdvisor最本质上的区别就是,IntroductionAdvisor只能应用于类级别的拦截,只能使用Introduction型的Advice,而不能像PointcutAdvisor那样,可以使用任何类型的Pointcut,以及差不多任何类型的Advice。也就是说,IntroductionAdvisor纯粹就是为Introduction而生的。
public static boolean canApply(Advisor advisor, Class targetClass, Class[] proxyInterfaces) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, proxyInterfaces);
}
else {
// It doesn't have a pointcut so we assume it applies
return true;
}
}
PointcutAdvisor的canApply:
public static boolean canApply(Pointcut pc, Class targetClass, Class[] proxyInterfaces) {
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// It may apply to the class
// Check whether it can apply on any method
// Checks public methods, including inherited methods
Method[] methods = targetClass.getMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
// If we're looking only at interfaces and this method
// isn't on any of them, skip it
if (proxyInterfaces != null && !methodIsOnOneOfTheseInterfaces(m, proxyInterfaces)) {
continue;
}
if (pc.getMethodMatcher().matches(m, targetClass))
return true;
}
return false;
}