基于spring 4.1.6
一、配置
只讨论<aop:config>形式的配置,对于ProxyFactory和@Aspect 形式暂不讨论,这两种形式只是前置流程不一样。
配置如下:
<!-- 目标服务 -->
<bean id="targetService" />
<!-- 通知 -->
<bean id="advisorService" />
<!-- 切面和代理 -->
<aop:config>
<aop:aspect id="advisor" ref="advisorService">
<aop:pointcut id="addAllMethod" expression="execution(* org.test.target.TargetServiceImpl.*(..))" />
<aop:before method="printTime" pointcut-ref="addAllMethod" />
<aop:after method="printTime" pointcut-ref="addAllMethod" />
</aop:aspect>
</aop:config>
二、AOP启动入口
spring AOP所有的一切都要从XML Namespace 说起,也就是AOP的启动入口。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
上述文件是Spring容器的配置文件的根标签,Spring解析到上述xmlns:aop后,会去一个Map中寻找其对应的Class全路径,对应关系所在文件位置:
aop jar包 META-INF/spring.handlers
内容:
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
通过这个类全路径可以加载一个类,该类会把IOC配置文件中的AOP配置加载容器中,此处注意,Spring中的很多组件都是这种方式加载到Spring的,另外Dubbo、RabbitMQ等也是如此。
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
* and '{@code scoped-proxy}' tags.
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
三、AOP初始化配置
接着上面的Namespace继续分析,下面是Namespacce解析类,代码中会区分默认Namespace和第三方组件Namespace,第三方中间件对接到Spring中,大部分通过Namespace形式对接。DefaultBeanDefinitionDocumentReader.class解析如下:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
// nl中包含所有的类""标签
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
} else {
// 每个Node中包含Namespace属性,第三方Namespace解析
delegate.parseCustomElement(ele);
}
}
}
} else {
// 非标签解析
delegate.parseCustomElement(root);
}
}
我们跟【delegate.parseCustomElement(ele)】进去,在BeanDefinitionParserDelegate.class中完成NamespaceHandler的获取,即【二、AOP启动入口】
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
// Namespace对应的类反射加载
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 这里解析 ParserContext包含了bean解析过程中所有的相关配置
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
解析【<aop:config>】,通过this.parsers.get()获取对应的解析类,该解析类参考【org.springframework.aop.config.AopNamespaceHandler】
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext).parse(element, parserContext);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
String localName = parserContext.getDelegate().getLocalName(element);
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
获取到BeanDefinitionParser,跟进到BeanDefinitionParser的实现类ConfigBeanDefinitionParser的parse(....)方法中。configureAutoProxyCreator(parserContext, element)非常关键,后续的针对这个对象进行AOP代理的生成,也是AOP的核心。
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 生成AspectJAwareAdvisorAutoProxyCreator对象,注册到Spring
configureAutoProxyCreator(parserContext, element);
List childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
} else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
} else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}
}
我们只针对ASPECT的解析进行分析,其他标签原理类似:
1、内部是for循环用于解析所有的<aop:advice>;
2、进一步解析<aop:advice>为RootBeanDefinition;
3、根据标签名称获取其类对象(比如AspectJMethodBeforeAdvice.class),然后获取<aop:before>的属性封装到ConstructorArgumentValues(用于封装构造函数参数);
4、第三步获取的AspectJMethodBeforeAdvice对象已经封装了相应的属性值,这些然后封装到AspectJPointcutAdvisor.class,该类中持有Pointcut、Advice和Order参数,这样就生成了一个Aspect;
5、获取所有的<aop:pointcut>标签
6、解析出来<aop:pointcut>中的表达式属性,并解析成RootBeanDefinition,然后注册到Spring
四、AOP生成代理
第二步已经把所有的标签生成了RootBeanDefinition,configureAutoProxyCreator(parserContext, element)这个方法生成了AOP核心类AspectJAwareAdvisorAutoProxyCreator,该类的类关系图:
AspectJAwareAdvisorAutoProxyCreator是BeanPostProcessor的实现类,核心就在postProcessAfterInitialization(....)这里,该方法会生成代理类。
Spring的启动过程在AbstractApplicationContext的refresh()进行。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// 创建BeanFactory,没有就创建,第二步就在这里发生的(BeanDefinition的装载)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 子类可以获取BeanFactoreanFactory
invokeBeanFactoryPostProcessors(beanFactory);
// 注册所有实现实现了BeanPostProcessor的类,存储在DefaultListableBeanFactory,beanFactory持有上述加载的所有的Bean,其中AspectJAwareAdvisorAutoProxyCreator也在其中
// 其中BeanId是org.springframework.aop.config.internalAutoProxyCreator,获取不到就create
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// 最关键的Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
最关键的是finishBeanFactoryInitialization(beanFactory),实例化所有非懒加载的Bean(回顾Bean的生命周期):
1、通过构造函数实例化
2、设置属性
3、回调BeanNameAware、BeanFactoryAware等接口子类的方法
4、遍历BeanPostProcessor的子类,然后回调他们的实现的两个方法(所谓BeanProcessor回调)
5、回调InitializingBean
6、ini-method属性....后续都是Bean的生命周期中的内容,关键要看第4步
当前Spring中有6个Bean和4个BeanPostProcessor:
举例说明,当根据Spring Bean生命周期,math在实例化(create)之前,调用BeanPostProcessor的子类的before方法,下面是代码片段:
上面的红框是用于调用BeanPostProcessor的前置方法,AOP的代理类在BeanPostProcessor的后置方法中生成。
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 调用后置处理器
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
接下来调用AbstractAutoProxyCreator的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;
}
我们跟wrapIfNecessary(bean, beanName, cacheKey),该方法只对math做了进一步的处理:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// this.advisedBeans这个map中包含beanI->boolean,不可以进一步则进入到下一步判断
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;
}
// 当前beanName如果有advice则可以为其创建代理,这里先去查找符合条件的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;
}
查找代理,接下来对当前beanName的符合条件的Advice进行查找:
AbstractAdvisorAutoProxyCreator
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
// 查找Advice
List advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List findEligibleAdvisors(Class beanClass, String beanName) {
// 所有的潜在Advice
List candidateAdvisors = findCandidateAdvisors();
// 选取符合条件的Advice
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors); // 在链表头添加一个默认ExposeInvocationInterceptor
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
/**
* Search the given candidate Advisors to find all Advisors that
* can apply to the specified bean.
* @param candidateAdvisors the candidate Advisors
* @param beanClass the target's bean class
* @param beanName the target's bean name
* @return the List of applicable Advisors
* @see ProxyCreationContext#getCurrentProxiedBeanName()
*/
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
AopUtils
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
/**
* Can the given pointcut apply at all on the given class?
* <p>This is an important test as it can be used to optimize
* out a pointcut for a class.
* @param pc the static or dynamic pointcut to check
* @param targetClass the class to test
* @param hasIntroductions whether or not the advisor chain
* for this bean includes any introductions
* @return whether the pointcut can apply on any method
*/
/** 获取pc的正则表达式,然后获取target的方法列表和正则表达式对比,满足返回true **/
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// Pointcut的正则表达式
MethodMatcher methodMatcher = pc.getMethodMatcher();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = clazz.getMethods(); // 目标对象的方法
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
获取了所有的Adivce后,就可以生成代理对象了:
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);
// proxy-target-class属性
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// Advice封装到ProxyFactory
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
// 根据配置生成代理
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
public Object getProxy(ClassLoader classLoader) {
// createAopProxy()获取代理,然后具体细节在getProxy()中
return createAopProxy().getProxy(classLoader);
}