什么是AOP
在分析AOP的实现之前,我们先来说说什么叫AOP。在面对对象开发中,我们总会发现程序中有一些重复的代码,这些代码穿插在业务功能的实现中,与业务代码耦合在一起,这时候就是AOP大显身手的时候。AOP即为面向切面编程,我们通过AOP将这部分代码抽取出来单独维护,封装到一个个切面中,并且为如何使用在何处使用这些代码对业务功能进行织入和增强提供了丰富灵活的手段。
AOP的基本概念
-
切面(Aspect):相当于OOP中的一个类,包含对于基础应用的增强逻辑,它是通知和切点的结合。
-
通知(Advice):通知包含具体增强的逻辑。Spring中有五种Advice:前置通知(Before Advice)、后置通知(After Advice)、返回通知(After Return Advice)、环绕通知(Around Advice)、抛出异常后通知(After Throwing Advice)。
-
连接点(Joinpoint):是指应用能够被切面切入的点,比如方法被调用时,抛出异常时。
-
切点(Pointcut):它定义了具体在何处切入横切逻辑,可以理解为某些类的某些方法。
AOP的实现原理
在这里我先说明一下,Spring的AOP是基于jdk的动态代理以及CGLIB的动态代理来实现的,如果对这部分内容不是太清楚的同学建议先去了解一下相关的内容再来阅读这篇文章。
我们先来看一个aop的小例子,首先定义一个切面类。
public class TestAspect {
public void before(){
System.out.println("before target method invoking");
}
public void after(){
System.out.println("after target method invoking");
}
}
然后定义一个待增强的目标类
public class TestAspectTarget {
public void pointcutMethod(){
System.out.println("this is point cut");
}
}
接下来是相关的配置文件testAOP.xml
<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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="aspect" class="TestAspect.TestAspect"></bean>
<bean id="target" class="TestAspect.TestAspectTarget"></bean>
<aop:config proxy-target-class="true">
<aop:aspect id="aspect" ref="aspect">
<aop:pointcut id="pointcut" expression="execution(* TestAspect.*.pointcutMethod(..))"></aop:pointcut>
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
</aop:aspect>
</aop:config>
</beans>
测试代码
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("TestAspect/testAOP.xml");
TestAspectTarget target = (TestAspectTarget) context.getBean("target");
target.pointcutMethod();
输出结果为
before target method invoking
this is point cut
1、AOP配置的解析过程
下面我们来分析AOP的实现原理。首先来看容器在解析配置文件时是如何处理的,前面的解析的这里直接跳过,我们直接看DefaultBeanDefinitionDocumentReader类中的parseBeanDefinitions方法,对这之前的解析的步骤有疑惑的同学可以看我的之前的文章 Spring源码解析(一):Spring的IOC实现。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
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 {
delegate.parseCustomElement(ele);
}
}
}
}
//如果不是Spring默认的namespace,则会用下面的方式进行解析,<aop:config>不是Spring默认的namespace,会进入下面的分支
else {
delegate.parseCustomElement(root);
}
}
下面来看看parseCustomElement的具体实现
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
//获取namespace路径,这里为http://www.springframework.org/schema/aop
String namespaceUri = getNamespaceURI(ele);
//获取namespace处理器,这里得到的是一个AopNamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//具体的解析的过程在这个parse方法中,这个方法的具体实现在AopNamespaceHandler的父类NamespaceHandlerSupport中
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
NamespaceHandlerSupport中parse方法如下
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext).parse(element, parserContext);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
//根据标签获取对应的BeanDefinitionParser,parses中有几个BeanDefinitionParser分别对应:
//config-->ConfigBeanDefinitionParser
//aspectj-autoproxy-->AspectJAutoProxyBeanDefinitionParser
//spring-configured-->SpringConfiguredBeanDefinitionParser
//在解析<aop:config>时,获取的是对应的ConfigBeanDefinitionParser
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;
}
下面来看看ConfigBeanDefinitionParser中的parse方法的实现
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
//向容器注册一个BeanName为org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition,
//默认为AspectJAwareAdvisorAutoProxyCreator,这个类是Spring的AOP的核心类,它的作用我们后面再说,然后这个
//方法中还有对proxy-target-class和expose-proxy这两个配置的相关处理
configureAutoProxyCreator(parserContext, element);
//对<aop:config>的子节点的相关处理
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
//对<aop:pointcut>的处理
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
}
//对<aop:advisor>的处理
else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
}
//对<aop:aspect>的处理
else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
下面看看configureAutoProxyCreator的具体实现
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}
public static void registerAspectJAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册AspectJAwareAdvisorAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//对proxy-target-class和expose-proxy这两个配置的相关处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//如果配置了org.springframework.aop.config.internalAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//如果没有配置就向容器注册一个BeanName为org.springframework.aop.config.internalAutoProxyCreator
//的BeanDefinition,默认为AspectJAwareAdvisorAutoProxyCreator
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
然后回到ConfigBeanDefinitionParser中的parse方法中,看看接下来对<aop:config>的下面的节点的处理,我们先来看看对<aop:aspect>的处理
private void parseAspect(Element aspectElement, ParserContext parserContext) {
//获取id属性和ref属性
String aspectId = aspectElement.getAttribute(ID);
String aspectName = aspectElement.getAttribute(REF);
try {
this.parseState.push(new AspectEntry(aspectId, aspectName));
List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
List<BeanReference> beanReferences = new ArrayList<BeanReference>();
//对<aop:declare-parents>配置的处理
List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
Element declareParentsElement = declareParents.get(i);
beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
}
//对aspect下面的advice标签的处理
NodeList nodeList = aspectElement.getChildNodes();
boolean adviceFoundAlready = false;
//遍历所有子节点
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
//如果为advice标签
if (isAdviceNode(node, parserContext)) {
if (!adviceFoundAlready) {
adviceFoundAlready = true;
if (!StringUtils.hasText(aspectName)) {
parserContext.getReaderContext().error(
"<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.",
aspectElement, this.parseState.snapshot());
return;
}
beanReferences.add(new RuntimeBeanReference(aspectName));
}
//对advice标签具体处理的过程
AbstractBeanDefinition advisorDefinition = parseAdvice(
aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
beanDefinitions.add(advisorDefinition);
}
}
AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
parserContext.pushContainingComponent(aspectComponentDefinition);
//遍历aspect下面的所有的pointcut标签
List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
for (Element pointcutElement : pointcuts) {
//对pointcut标签具体的处理过程
parsePointcut(pointcutElement, parserContext);
}
parserContext.popAndRegisterContainingComponent();
}
finally {
this.parseState.pop();
}
}
先来看看isAdviceNode方法中是如何判断是否为advice标签的
private boolean isAdviceNode(Node aNode, ParserContext parserContext) {
if (!(aNode instanceof Element)) {
return false;
}
else {
//如果标签为<aop:before>、<aop:after>、<aop:after-returning>、<aop:after-throwing>、
//<aop:around>中的一个,return true
String name = parserContext.getDelegate().getLocalName(aNode);
return (BEFORE.equals(name) || AFTER.equals(name) || AFTER_RETURNING_ELEMENT.equals(name) ||
AFTER_THROWING_ELEMENT.equals(name) || AROUND.equals(name));
}
}
然后来看看对advice标签的具体的处理过程
private AbstractBeanDefinition parseAdvice(
String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
try {
this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));
// create the method factory bean
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true);
// create instance factory definition
RootBeanDefinition aspectFactoryDef =
new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);
// 创建一个advice对应的BeanDefinition——adviceDef
AbstractBeanDefinition adviceDef = createAdviceDefinition(
adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
beanDefinitions, beanReferences);
// 根据adviceDef生成一个新的BeanDefinition——advisorDefinition
RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
}
// 将advisorDefinition 注册到容器中
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
return advisorDefinition;
}
finally {
this.parseState.pop();
}
}
createAdviceDefinition方法的具体实现如下
private AbstractBeanDefinition createAdviceDefinition(
Element adviceElement, ParserContext parserContext, String aspectName, int order,
RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
//根据advice标签的配置获取对应的class并生成BeanDefinition
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
//根据advice中的对应配置的属性设置对应的值
adviceDefinition.setSource(parserContext.extractSource(adviceElement));
adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
if (adviceElement.hasAttribute(RETURNING)) {
adviceDefinition.getPropertyValues().add(
RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
}
if (adviceElement.hasAttribute(THROWING)) {
adviceDefinition.getPropertyValues().add(
THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
}
if (adviceElement.hasAttribute(ARG_NAMES)) {
adviceDefinition.getPropertyValues().add(
ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
}
ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
//解析advice标签中pointcut的相关配置
Object pointcut = parsePointcutProperty(adviceElement, parserContext);
if (pointcut instanceof BeanDefinition) {
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
beanDefinitions.add((BeanDefinition) pointcut);
}
else if (pointcut instanceof String) {
RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
beanReferences.add(pointcutRef);
}
cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
return adviceDefinition;
}
看下getAdviceClass中是如何根据advice标签的配置获取对应的class
private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
String elementName = parserContext.getDelegate().getLocalName(adviceElement);
//根据标签获取对应的class:<aop:before>-->AspectJMethodBeforeAdvice、
//<aop:after>-->AspectJAfterAdvice、
//<aop:after-returning>-->AspectJAfterReturningAdvice、
//<aop:after-throwing>-->AspectJAfterThrowingAdvice、
//<aop:around>-->AspectJAroundAdvice
if (BEFORE.equals(elementName)) {
return AspectJMethodBeforeAdvice.class;
}
else if (AFTER.equals(elementName)) {
return AspectJAfterAdvice.class;
}
else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
return AspectJAfterReturningAdvice.class;
}
else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
return AspectJAfterThrowingAdvice.class;
}
else if (AROUND.equals(elementName)) {
return AspectJAroundAdvice.class;
}
else {
throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
}
}
parsePointcutProperty方法中对pointcut的配置的解析如下
private Object parsePointcutProperty(Element element, ParserContext parserContext) {
//如果同时定义了pointcut和pointcut-ref会报错
if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) {
parserContext.getReaderContext().error(
"Cannot define both 'pointcut' and 'pointcut-ref' on <advisor> tag.",
element, this.parseState.snapshot());
return null;
}
//如果定义了pointcut那么根据配置返回一个BeanDefinition
else if (element.hasAttribute(POINTCUT)) {
// Create a pointcut for the anonymous pc and register it.
String expression = element.getAttribute(POINTCUT);
AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(element));
return pointcutDefinition;
}
//如果定义的是pointcut-ref那么直接返回pointcut-ref属性中的字符串
else if (element.hasAttribute(POINTCUT_REF)) {
String pointcutRef = element.getAttribute(POINTCUT_REF);
if (!StringUtils.hasText(pointcutRef)) {
parserContext.getReaderContext().error(
"'pointcut-ref' attribute contains empty value.", element, this.parseState.snapshot());
return null;
}
return pointcutRef;
}
else {
parserContext.getReaderContext().error(
"Must define one of 'pointcut' or 'pointcut-ref' on <advisor> tag.",
element, this.parseState.snapshot());
return null;
}
}
parseAdvice方法中就是这些内容,回到parseAspect方法中,接下里就是对pointcut标签的处理,处理的过程主要是在parsePointcut方法中,来看看这个方法的具体实现
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
//获取pointcut标签的id、expression属性
String id = pointcutElement.getAttribute(ID);
String expression = pointcutElement.getAttribute(EXPRESSION);
AbstractBeanDefinition pointcutDefinition = null;
try {
this.parseState.push(new PointcutEntry(id));
//创建pointcut标签对应的BeanDefinition
pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
String pointcutBeanName = id;
//向容器注册这个BeanDefinition
if (StringUtils.hasText(pointcutBeanName)) {
parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
}
else {
pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
}
//向容器注册一个Pointcut组件定义
parserContext.registerComponent(
new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
}
finally {
this.parseState.pop();
}
return pointcutDefinition;
}
protected AbstractBeanDefinition createPointcutDefinition(String expression) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanDefinition.setSynthetic(true);
beanDefinition.getPropertyValues().add(EXPRESSION, expression);
return beanDefinition;
}
<aop:aspect>标签的解析就结束了。我们在看看对于<aop:advisor>标签是如何进行解析的,具体的解析过程的实现在parseAdvisor方法中。
private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
//创建一个advisor标签对应的BeanDefinition
AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
String id = advisorElement.getAttribute(ID);
try {
this.parseState.push(new AdvisorEntry(id));
String advisorBeanName = id;
//向容器注册这个BeanDefinition
if (StringUtils.hasText(advisorBeanName)) {
parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
}
else {
advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
}
//解析标签中的pointcut的相关配置,上面已经分析过这个方法,这里就不再说明了
Object pointcut = parsePointcutProperty(advisorElement, parserContext);
//将pointcut属性的解析结果添加到propertyValues中
if (pointcut instanceof BeanDefinition) {
advisorDef.getPropertyValues().add(POINTCUT, pointcut);
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
}
else if (pointcut instanceof String) {
advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef));
}
}
finally {
this.parseState.pop();
}
}
AOP相关的配置的解析到这里就结束了,所有的配置就已经转换成了对应的BeanDefinition并存放在容器中,接下来就是具体的AOP的实现过程。
2、AOP的实现
在前面我们分析ConfigBeanDefinitionParser中的parse方法时,看到了这个方法中向容器注册一个BeanName为org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition,默认为AspectJAwareAdvisorAutoProxyCreator,这个类实现了BeanPostProcessor接口,就是这个类中的postProcessAfterInitialization方法触发了为AOP配置的BeanDefinition创建代理的过程。在上一篇Spring源码解析(二):容器的其他相关特性 说过,在解析载入Bean时,在DefaultListableBeanFactory的preInstantiateSingletons方法中会触发对容器中所有singleton并且未配置lazy-init属性或者lazy-init为false的Bean的依赖注入,在依赖注入过程中会调用AbstractAutowireCapableBeanFactory的initializeBean方法,如果Bean实现了BeanPostProcessor,这个方法中会触发对postProcessAfterInitialization的调用,如果想详细了解这个调用过程的话可以参考我的上一篇文章。下面来看看AspectJAwareAdvisorAutoProxyCreator中的postProcessAfterInitialization,这个方法的实现在它的父类AbstractAutoProxyCreator中。
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;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
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;
}
// 获取需要在目标对象上增强的advisors
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;
}
getAdvicesAndAdvisorsForBean方法的实现在AbstractAdvisorAutoProxyCreator类中,具体代码如下
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取候选的Advisor集合
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//在候选的Advisor中找到要增强在目标对象上的Advisor链
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//如果Advisor集合中没有DefaultPointcutAdvisor,从eligibleAdvisors的头部(index=0)添加一个DefaultPointcutAdvisor
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = null;
synchronized (this) {
//从缓存中获取已经处理过的advisorNames
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
//获取前面解析配置文件时得到的Advisor的BeanName
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
//将处理过的advisorNames缓存起来
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
//根据advisorNames获取对应的Advisor添加到集合中
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
再来看看如何从候选的advisors中获取需要代理的advisor
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中的findAdvisorsThatCanApply方法具体实现如下
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
//如果为空直接返回
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
//处理IntroductionAdvisor
for (Advisor candidate : candidateAdvisors) {
//具体的判断在canApply方法中
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
//处理非IntroductionAdvisor
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//具体的判断在canApply方法中
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
canApply方法的实现如下
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
//对于一般的advice(before,after,After-Return,Around,After-Throwing),前面的解析过程会得到
//一个AspectJPointcutAdvisor,所以会进入下面的分支
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;
}
}
然后会调用一个重载的canApply方法,这个方法中会完成具体的判断
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//判断目标类是否满足Advisor中定义的pointcut的expression表达式的匹配规则
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
//得到目标类所有实现的接口及目标类Class,存放到一个Set中
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
//遍历得到的Set
for (Class<?> clazz : classes) {
//取得类中定义的所有方法,包括父类的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
//遍历所有的方法
for (Method method : methods) {
//如果有一个能匹配pointcut中的expression表达式就返回true
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
到这里就拿到了所有需要在目标对象上增强的advisors,然后回到AbstractAutoProxyCreator中的wrapIfNecessary中,接下来就是具体创建代理的过程。这个过程的实现在方法createProxy中,具体代码如下
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 proxyFactory = new ProxyFactory();
//设置一些属性值
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//将要增强的advisor添加到proxyFactory中
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
//这个方法留给子类实现,用户可以用这个方法定制一些操作
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
//advisorsPreFiltered方法默认返回true
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//这里是具体创建代理的地方
return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
//createAopProxy方法返回一个AopProxy的实现,AopProxy由两个子类实现,
//一个是CglibAopProxy,一个是JdkDynamicAopProxy,很显然对于这两个类Spring分别通过CGLIB代理和JDK动态代
//理来生成需要的代理对象
return createAopProxy().getProxy(classLoader);
}
下面来看看createAopProxy这个方法的实现
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//getAopProxyFactory默认得到的是DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory中的createAopProxy方法代码如下
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//如果代理的目标对象为接口的实现并且没有配置proxy-target-class="true"属性,那么使用JDK的动态代理,
//否则使用CGLIB代理
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);
}
}
具体的生成代理对象的过程由JdkDynamicAopProxy和CglibAopProxy的getProxy方法来完成,我们先来看看JdkDynamicAopProxy中的getProxy方法的实现
2.1 JDK代理实现AOP
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
//拿到目标对象实现的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
//判断目标类中是否实现了equals和hashCode方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//如果对JDK代理熟悉的同学一眼就能看出来这里就是创建代理对象的地方
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
用newProxyInstance方法生成代理对象时,第三个参数需要传入一个InvocationHandler的实现,InvocationHandler这个接口中定义了一个invoke方法,这个方法在代理对象的代理方法被调用时会被回调触发,而JdkDynamicAopProxy本身就是InvocationHandler的实现,所以这里直接将this传入newProxyInstance方法中。JdkDynamicAopProxy的invoke方法中完成了获取目标对象并将配置中的advisor转换为对应的拦截器链并在目标对象上进行增强的过程。下面来看看这个invoke的实现
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
//如果调用的是equals方法并且目标对象没有实现equals方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
//如果调用的是hashCode方法并且目标对象没有实现hashCode方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
//根据代理对象的配置来调用服务
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//如果配置了expose-proxy属性
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//获取目标对象
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 将advisors转换为拦截器链,这个advised是一个AdvisedSupport对象,AdvisedSupport是
//ProxyFactory的父类,这个类中封装了AOP对advise和advisor的相关操作
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果没有配置拦截器,那么直接通过反射调用目标类的对应方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
//如果配置了拦截器,那么需要调用拦截器之后再调用目标的方法,这个过程通过ReflectiveMethodInvocation
//的proceed方法来实现。
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
来看看getInterceptorsAndDynamicInterceptionAdvice方法是如何取得拦截器链的
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
//先从从缓存中取
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
//如果取不到那么通过advisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法生成,
//然后加入到缓存中,advisorChainFactory是一个DefaultAdvisorChainFactory对象
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
// 根据advisors的个数创建一个List
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
//获取代理对象的Class
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
//是否匹配IntroductionAdvisor
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
//这个registry非常重要,拦截器链就是通过这个registry来加入的,这个registry是一个单例模式的实现
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//遍历advisors
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//获取拦截器链
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
//MethodMather是一个接口,用来判断是否需要对当前调用方法进行增强,
//具体的判断逻辑在MethodMather的matches方法中
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//进行匹配判断,如果匹配成功就加入拦截器链
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
在上面的代码中我们看到,拦截器的生成是通过registry.getInterceptors(advisor)来完成的,这个registry是一个单例的AdvisorAdapterRegistry的实现,它由GlobalAdvisorAdapterRegistry类的getInstance方法创建,我们来看看GlobalAdvisorAdapterRegistry的实现。
public abstract class GlobalAdvisorAdapterRegistry {
//使用一个静态的类变量来保持一个唯一的实例
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
//返回单例的DefaultAdvisorAdapterRegistry对象
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
static void reset() {
instance = new DefaultAdvisorAdapterRegistry();
}
}
现在我们知道了registry实际上是一个DefaultAdvisorAdapterRegistry对象,在这个类中设置了一系列AdvisorAdapter,这是适配器模式的 一个很好的应用,adaptee就是一系列的advice,这个类中代码如下
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
//持有一个AdvisorAdapter的List,这个List中的adapter是与AOP的实现增强的advise对应
private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
//在构造器中加入一些Adapter,分别对应MethodBeforeAdvice、AfterReturningAdvice、ThrowsAdvice
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
//这是在DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法中调用的
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
//取出Advisor通知器中的advice通知
Advice advice = advisor.getAdvice();
//如果通知是MethodInterceptor类型的,那么直接加入interceptors中,不需要适配
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//对通知进行适配
for (AdvisorAdapter adapter : this.adapters) {
//适配器是否匹配,如果匹配的那么调用getInterceptor方法取得封装好的拦截器
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
以MethodBeforeAdviceAdapter为例,我们来了解下这些适配器是如何工作的,MethodBeforeAdviceAdapter代码实现如下
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
这个类的实现非常简单,它只有两个方法,一个supportsAdvice方法用来判断advice是否匹配,supportsAdvice方法返回一个MethodBeforeAdviceInterceptor拦截器。这样我们就已经从advisor中获取到了对应的拦截器对象,现在我们回到JdkDynamicAopProxy的invoke方法中,获取到拦截器链之后就是通过ReflectiveMethodInvocation中的proceed方法对目标方法进行增强
public Object proceed() throws Throwable {
//currentInterceptorIndex默认值为-1,interceptorsAndDynamicMethodMatchers是由构造器传入的拦截器链,如果拦截器链中的拦截器调用完毕,会通过反射调用目标对象的对应方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//沿着定义好的拦截器链进行处理
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果拦截器链为InterceptorAndDynamicMethodMatcher类型
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
//如何advice和定义的pointcut匹配,那么将会执行
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
//如果不匹配,那么递归调用proceed,直到所有拦截器被调用为止
return proceed();
}
}
else {
//如果只是一个interceptor那么直接调用这个interceptor的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
然后会调用拦截器的invoke方法,我们来看看MethodBeforeAdviceInterceptor方法中的invoke方法的实现
public Object invoke(MethodInvocation mi) throws Throwable {
//先调用advice的before方法,这个方法中就是MethodBeforeAdvice对目标对象的增强逻辑
//然后继续递归调用proceed方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
如果是用我上面的配置方式,这个advice就是一个AspectJMethodBeforeAdvice,它的before方法会用反射的方式调用<aop:before>标签中定义的方法,你也可以定义自己的advice类,实现MethodBeforeAdvice即可,那么这里就会调用你自己定义的类中before方法。其他的几种interceptor的invoke回调方法的逻辑如果大家感兴趣的话可以自行了解。这就是Spring通过JDK代理的方式为目标类生成代理的过程,下面我们来看看Spring是如何使用CGLIB来为目标类生成代理的。这个创建代理对象的过程也是在AopProxy的接口方法getProxy中完成的,我们来看看CglibAopProxy这个类中的getProxy方法的实现
2.2 CGLIB实现AOP
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
//获取目标类的class对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
//添加代理类的接口
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Enhancer是CGLIB的主要操作类
Enhancer enhancer = createEnhancer();
//设置enhancer的相关属性
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
//获取回调
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
//设置回调拦截器
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 这里生成代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Exception ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
CGLIB的主要操作类是Enhancer,与JDK代理类似中的invoke方法类似,对Enhancer方法也要设置一系列的回调来进行对目标累的调用方法的拦截与增强,不一样的是CGLIB中可以为Enhancer设置一系列的回调,然后通过为Enhancer设置一个CallBackFilter来对不同的调用方法执行不同的回调,而JDK动态代理中InvocationHandler的回调方法invoke对所有执行的方法都有效。获取回调的过程是在getCallbacks方法中实现的,我们来看看这个方法的代码
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// 主要是这个拦截器来完成AOP功能
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
}
else {
targetInterceptor = isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
//定义一系列拦截器
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimisations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
// TODO: small memory optimisation here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(methods[x].toString(), x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
而对于AOP的拦截调用主要是在DynamicAdvisedInterceptor这个拦截器中,它是一个MethodInterceptor的实现,MethodInterceptor继承自CallBack,与InvocationHandler中的invoke方法类似,它的回调的逻辑主要是在intercept方法中,我们来看看这个方法的实现
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we
// "own" the target, in case it comes from a pool...
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
//获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果没有AOP通知配置那么直接调用目标对象的方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 由CglibMethodInvocation这个类来进行拦截器链的调用
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
可以看到,这个方法中的逻辑其实与invoke方法中非常类似,都是由getInterceptorsAndDynamicInterceptionAdvice方法先由配置的通知获取对应的拦截器链然后调用,getInterceptorsAndDynamicInterceptionAdvice方法上面已经分析过了,而CglibMethodInvocation其实就是ReflectiveMethodInvocation的子类,它在这里调用的就是ReflectiveMethodInvocation的proceed方法,这里就不再赘述了。至此,Spring的AOP的实现过程就已经结束了。