Spring加载时,会使用ClassLoader去查找所有能找到的"META-INF/spring.handlers"文件,并存放在handlerMappings中(DefaultNamespaceHandlerResolver在干这事),遇到除beans外的Namespace,就会去这里查找对应的解析器,如果不存在就报错,存在就使用相应的解析器进行解析。
<aop>是由AopNamespaceHandler来进行解析的。
AspectJAutoProxyBeanDefinitionParser会注册3个类来处理解析任务,分别对应为:
"config", new ConfigBeanDefinitionParser();
"aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser();
"scoped-proxy", new ScopedProxyBeanDefinitionDecorator();
要使用aop命名空间,需要在spring的xml中加入:
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-xsd"
这样便可以在该xml中使用<aop .../>了。
<aop:aspectj-autoproxy/>
使用该配置后,AspectJAutoProxyBeanDefinitionParser会注册AnnotationAwareAspectJAutoProxyCreator到Spring管理的bean中。由于AnnotationAwareAspectJAutoProxyCreator是BeanPostProcessor,所以在所有bean初始化完成后,都会调用该类中的postProcessAfterInitialization来进行处理。
AnnotationAwareAspectJAutoProxyCreator使用findEligibleAdvisors来查找是否有bean对应的Advisors(注册在当前beanFactory中的实现了Advisor接口的类,例如BeanFactoryTransactionAttributeSourceAdvisor),如果有,创建一个该bean的代理(AbstractAutoProxyCreator)。
如果使用了<tx:annotation-driven/>,其中的mode属性默认为proxy,解析到这里的时候,AnnotationDrivenBeanDefinitionParser会自动调用AopNamespaceUtils->AopConfigUtils,而AopConfigUtils会把AnnotationAwareAspectJAutoProxyCreator注册到beanFactory里面去,也就是相当于写了个<aop:aspectj-autoproxy/>的标签。
如果不知道程序应该使用Spring-AOP还是AspectJ,这儿有较好的描述:
Spring-AOP默认使用JDKProxy来代理实现了任何接口的类,如果没有实现任何接口,则使用Cglib2AopProxy来创建代理,对原类的方法调用时,会根据代理类设置的Callback[]进行相应处理。
Spring-AOP默认设置的Callback有
DynamicAdvisedInterceptor(拦截方法调用,检查需要使用的拦截器并执行,例如TransactionInterceptor)
DynamicUnadvisedInterceptor/StaticUnadvisedInterceptor
StaticDispatcher
AdvisedDispatcher(不知道拿来干嘛的)
EqualsInterceptor
HashCodeInterceptor
SerializableNoOp(貌似没啥用?)