Spring AOP实现逻辑源码分析小结
AspectJAutoProxyRegistrar 根据@EnableAspectJAutoProxy或<aop:aspectj-autoproxy/>注册AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator
DefaultAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator
InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator
AbstractAdvisorAutoProxyCreator extends SmartInstantiationAwareBeanPostProcessor
AbstractAdvisorAutoProxyCreator->getAdvicesAndAdvisorsForBean;findEligibleAdvisors;findCandidateAdvisors;
ReflectiveAspectJAdvisorFactory
BeanFactoryAspectJAdvisorsBuilder->buildAspectJAdvisors
MetadataAwareAspectInstanceFactory BeanFactoryAspectInstanceFactory;
InstantiationModelAwarePointcutAdvisorImpl
AspectJPointcutAdvisor使用AspectJAroundAdvice作为参数,其中SimpleBeanFactoryAwareAspectInstanceFactory是AspectInstanceFactory在解析xml创建advice的实现类。
AspectJExpressionPointcut
AspectJAroundAdvice or MethodInterceptor
$$$bean创建时会被代理,在AbstractAutoProxyCreator中,创建bean之前会调用所有advisor的getPointCut,来匹配bean的类和方法
TargetSource应用说明:TargetSource Developers using Spring AOP don’t normally need to work directly with TargetSources, but this provides a powerful means of supporting pooling, hot swappable and other sophisticated targets.The org.springframework.aop.target.HotSwappableTargetSource exists to allow the target of an AOP proxy to be switched while allowing callers to keep their references to it. 能够实现热加载,热交换bean。
ApplicationContext加载生成过程参见AbstractApplicationContext.refresh方法。
1、obtainFreshBeanFactory创建DefaultListableBeanFactory作为beanFactory
2、obtainFreshBeanFactory加载xml,生成BeanDefinition(GenericBeanDefinition??)
3、prepareBeanFactory配置beanFactory的属性,比如添加BeanPostProcessor->LoadTimeWeaverAwareProcessor
4、postProcessBeanFactory添加ApplicationContext子类独有的BeanPostProcessor
5、invokeBeanFactoryPostProcessors调用BeanFactoryPostProcessor,首先调用BeanDefinitionRegistryPostProcessor类型的,然后调用其他类型的.其中ConfigurationClassPostProcessor是其子类,用来处理@Configuration classes,在xml中声明<context:annotation-config/> or <context:component-scan/>时生成beandefinition。
6、registerBeanPostProcessors生成常规的BeanPostProcessor的实例,并添加到BeanPostProcessor列表
7、initMessageSource
8、initApplicationEventMulticaster
9、onRefresh
10、registerListeners
11、finishBeanFactoryInitialization,Instantiate all remaining (non-lazy-init) singletons初始化所有singletons bean(not-lazy),生成bean的过程(loadclass->preconstruct->new instance->postconstruct->set properties->bean post process->initialize)
12、finishRefresh
B1、BeanPostProcess与依赖的说明:
BeanPostProcessors and AOP auto-proxying
Classes that implement the BeanPostProcessor interface are special and are treated differently
by the container. All BeanPostProcessors and beans that they reference directly are
instantiated on startup, as part of the special startup phase of the ApplicationContext. Next,
all BeanPostProcessors are registered in a sorted fashion and applied to all further beans in the
container. Because AOP auto-proxying is implemented as a BeanPostProcessor itself, neither
BeanPostProcessors nor the beans they reference directly are eligible for auto-proxying, and
thus do not have aspects woven into them.
For any such bean, you should see an informational log message: "Bean foo is not eligible
for getting processed by all BeanPostProcessor interfaces (for example: not eligible for autoproxying)".
Note that if you have beans wired into your BeanPostProcessor using autowiring or
@Resource (which may fall back to autowiring), Spring might access unexpected beans when
searching for type-matching dependency candidates, and therefore make them ineligible for
auto-proxying or other kinds of bean post-processing. For example, if you have a dependency
annotated with @Resource where the field/setter name does not directly correspond to the
declared name of a bean and no name attribute is used, then Spring will access other beans for
matching them by type.
B2、BeanFactoryPostProcessor的说明:
If you want to change the actual bean instances (i.e., the objects that are created from the
configuration metadata), then you instead need to use a BeanPostProcessor (described
above in the section called “Customizing beans using a BeanPostProcessor”). While it is
technically possible to work with bean instances within a BeanFactoryPostProcessor (e.g.,
using BeanFactory.getBean()), doing so causes premature bean instantiation, violating the
standard container lifecycle. This may cause negative side effects such as bypassing bean post
processing.
Also, BeanFactoryPostProcessors are scoped per-container. This is only relevant if you are
using container hierarchies. If you define a BeanFactoryPostProcessor in one container, it
will only be applied to the bean definitions in that container. Bean definitions in one container
will not be post-processed by BeanFactoryPostProcessors in another container, even if both
containers are part of the same hierarchy.
B2.1、PropertyPlaceholderConfigurer是个BeanFactoryPostProcessor,获取.properties文件的内容并替换BeanDefinition,其中<context:property-placeholder location="classpath:com/foo/jdbc.properties"/>标签与<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:com/foo/jdbc.properties"/></bean>效果相同
B3、Annotation injection is performed before XML injection, thus the latter configuration will override
the former for properties wired through both approaches.
B4、<context:annotation-config/> The implicitly registered post-processors include AutowiredAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor, as
well as the aforementioned RequiredAnnotationBeanPostProcessor.注册多个beanpostprocessors。注意:<context:annotation-config/> only looks for annotations on beans in the same applicationcontext in which it is defined。比如dispatcher和service 的两个context.
The use of <context:component-scan> implicitly enables the functionality of <context:annotation-config>. There is usually no need to include the<context:annotation-config> element when using <context:component-scan>.
Furthermore, the AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor are both included implicitly when you use the componentscan element. That means that the two components are autodetected and wired together - all without any bean configuration metadata provided in XML.
B5、EnableLoadTimeWeaving与<context:load-time-weaver/>作用相同。
EnableAspectJAutoProxy与<aop:aspectj-autoproxy/>作用相同。注册自动代理创建者AnnotationAwareAspectJAutoProxyCreator。切面bean仍旧需要在xml中定义,spring检测bean是否具有@aspect注解。
除了使用@aspect注解外,也可以通过xml的方式生成切面,<aop:config>标签会在ConfigBeanDefinitionParser->configureAutoProxyCreator函数中生效。Within your Spring configurations, all aspect and advisor elements must be placed within an
<aop:config> element (you can have more than one <aop:config> element in an application
context configuration). An <aop:config> element can contain pointcut, advisor, and aspect elements
(note these must be declared in that order).Warning
The <aop:config> style of configuration makes heavy use of Spring’s auto-proxying
mechanism. This can cause issues (such as advice not being woven) if you are already
using explicit auto-proxying via the use of BeanNameAutoProxyCreator or suchlike. The
recommended usage pattern is to use either just the <aop:config> style, or just the
AutoProxyCreator style.
<aop:config proxy-target-class="true">
<!-- other beans defined here... -->
</aop:config>
<aop:aspectj-autoproxy proxy-target-class="true"/>
说明:To be clear: using 'proxy-target-class="true"' on <tx:annotation-driven/>,
<aop:aspectj-autoproxy/> or <aop:config/> elements will force the use of CGLIB
proxies for all three of them.
B6、容器外对象注入。缺省情况下的容器外对象注入,该容器外对象虽然是被创建的却不能被代理。
@EnableSpringConfigured和<context:spring-configured/>作用相同,都是扫描@Configurable,比如@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)
这种注入要求在容器内有prototype的bean,定义,而且和@Configurable("name")相同,由于要依赖AnnotationBeanConfigurerAspect,所以
<bean id="myService"
class="com.xzy.myapp.service.MyService"
depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect">。除了以上配置,需要LoadTimeWeaver织入AnnotationBeanConfigurerAspect。javaagent和instrument是需要的。
B7、NamespaceHandler是来处理xml中的命名空间的处理器,通过不同的handler,处理不同的element。AopNamespaceHandler专门用来处理namespace=aop的element,比如aop:config,aop:aspectj-autoproxy,aop:scoped-proxy。
B8、11.8 Manipulating advised objects
However you create AOP proxies, you can manipulate them using the org.springframework.aop.framework.Advised interface. Any AOP proxy can be cast to this
interface, whichever other interfaces it implements.
B9、关于bean的实例化与BeanFactory的getBean方法,都在AbstractBeanFactory类中实现,getBean 委托给doGetBean,按名字创建实例,然后给getObjectForBeanInstance处理。
getObjectForBeanInstance首先看需要的是FactoryBean,还是FactoryBean生产的bean.如果是一个isSynthetic的bean,则不进行post-processing。
什么是synthetic的bean呢.spring 注释 Set whether this bean definition is 'synthetic', that is, not defined by the application itself (for example, an infrastructure bean such as a helper for auto-proxying, created through {@code <aop:config>}
B10、spring获取资源的方式。使用PathMatchingResourcePatternResolver解析location返回Resource,支持classpath:,classpath*:,file:,jar:
没有通配符的情况No Wildcards:
In the simple case, if the specified location path does not start with the "classpath*:" prefix, and does not contain a PathMatcher pattern,
this resolver will simply return a single resource via a getResource() call on the underlying ResourceLoader.
Examples are real URLs such as "file:C:/context.xml", pseudo-URLs such as "classpath:/context.xml", and simple unprefixed paths such as "/WEB-INF/context.xml".
The latter will resolve in a fashion specific to the underlying ResourceLoader (e.g. ServletContextResource for a WebApplicationContext).
Ant风格的Ant-style Patterns:
When the path location contains an Ant-style pattern, e.g.:
/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml
classpath*: Prefix:
There is special support for retrieving multiple class path resources with the same name, via the "classpath*:" prefix.
For example, "classpath*:META-INF/beans.xml" will find all "beans.xml" files in the class path, be it in "classes" directories or in JAR files.
This is particularly useful for autodetecting config files of the same name at the same location within each jar file. Internally, this happens via a ClassLoader.getResources() call, and is completely portable.
注意:如果使用了classpath*:*.xml ,则不会得到jar根目录下的资源文件。
classpath 只会到classes目录下去查找资源,classpath*:会包括jar的文件
B11、spring的类型自动转换。相关的类包括BeanWapper,TypeConverterDelegate,ResourceEditorRegistrar.
a.AbstractApplicationContext.prepareBeanFactory中加入ResourceEditorRegistrar.
B12、自定义命名空间和标签。XSD,namespacehandler,parser,META-INF/spring.handlers,META-INF/spring.schemas