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;

扫描二维码关注公众号,回复: 352097 查看本文章

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

猜你喜欢

转载自currentj.iteye.com/blog/2313237