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"
xmlns:contexts="http://www.springframework.org/schema/context"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<contexts:annotation-config />
<contexts:component-scan base-package="com.telecom.spring.inside"/>
<context:property-placeholder location="classpath:config/bean.properties"/>
<aop:aspectj-autoproxy>
aop:aspectj-autoproxy>
beans>
Java:
@Component
public class HealthService {
/**
* 待代理的方法
*/
public String echo(String message){
System.out.println(message)
return message;
}
}
Main:
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("config/Bootstrap_${env}.xml");
HealthService healthService = (HealthService) classPathXmlApplicationContext.getBean("healthService");
healthService.echo("hello");
}
public class AopNamespaceHandler extends NamespaceHandlerSupport {
@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());
}
}
概述:假定您已经知道自定义元素的解析过程。
加载BeanDefinition时,当遇到< aop:aspectj-autoproxy />,DefaultNamespaceHandlerResolver会根据元素的命名空间URI,搜索出其对应的NamespaceHandler,即AopNamespaceHandler,然后根据元素类型,找到其对应的BeanDefinitionParser,即AspectJAutoProxyBeanDefinitionParser。调用其parse(Element element, ParserContext parserContext)方法,对给定的元素(即< aop:aspectj-autoproxy />元素)进行解析。
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//1,0 如果需要的话,注册一个AspectJ的自动代理创建器:AnnotationAwareAspectJAutoProxyCreator
// 注册到BenaDefinitionRegustry上哟!!
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 因为允许有子节点,即 ,
// 用于约束切面仅对满足该命名规范的Bean生效,该方法的目的就是将所解析出的name,
// 添加到BeanDefinition的includePattern属性上,这些name都是一些正则表达式,用于匹配Bean的名字
extendBeanDefinition(element, parserContext);
return null;
}
}
重点显而易见,下面着重分析AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
public abstract class AopNamespaceUtils {
public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";
private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//1.0 注册AspectJ的自动代理创建器:AnnotationAwareAspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//2.0 分别处理中的子元素:proxy-target-class和expose-proxy
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
//提取proxy-target-class属性的值,并强制修改BeanDefinition的属性
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//提取expose-proxy属性的值,并强制修改BeanDefinition的属性
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
public abstract class AopConfigUtils {
//强制修改BeanDefnition
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
}
AopNamespaceUtils的处理逻辑比较简单,先注册一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition到BeanDefinitionRegistry上,它是一个BeanPostProcessor,在Bean的init-method调用前后执行,完成对目标对象的代理,一会就会讲到。然后,因为< aop:aspectj-autoproxy />中还有两个配置元素:
public class SimplePojo implements Pojo {
//foo 调用 bar,如果直接bar(),那么我们会发现,bar()方法并未被切面代理,而是直接调用的原生方法,这与Spring的Aop内存模型有关
public void foo() {
// this works, but... gah!
((Pojo) AopContext.currentProxy()).bar();
}
public void bar() {
// some logic...
}
}
接下来,我们来看到底是如何注册AnnotationAwareAspectJAutoProxyCreator的:
public abstract class AopConfigUtils {
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 调用其他方法
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
//注册或升级Aop相关的的BeanPostProcessor
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//如果注册中心中存在BeanName = AUTO_PROXY_CREATOR_BEAN_NAME的BeanDefinition
// 那么需要判断谁的优先级更高一点,保留优先级最高的那一个
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 提取出BeanName = AUTO_PROXY_CREATOR_BEAN_NAME的BeanDefinition
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 如果Bean的类名是相同的,那么无需重复注册,如果类名不一致,则比较优先级,保留优先级最高的
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 = AUTO_PROXY_CREATOR_BEAN_NAME的BeanDefinition
// 那么创建一个,类名是传入的参数指定的,本例中则是AnnotationAwareAspectJAutoProxyCreator,并注册到BeanDefinitionRegistry上
// 并将其类型角色设置为基础设施,优先级设置为最高
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;
}
}
前面,我们学习了注册AnnotationAwareAspectJAutoProxyCreator,它是SmartInstantiationAwareBeanPostProcessor的实现,而SmartInstantiationAwareBeanPostProcessor是InstantiationAwareBeanPostProcessor的子接口。
下面我们将所有相关的方法,笼聚到AnnotationAwareAspectJAutoProxyCreator方便查看:
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
// 由自定义的TargetSource代理的Bean的缓存集合
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 循环引用时使用,用于暗示该beanName对应的Bean实例被循环引用了
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
// 代理类型缓存,键为beanName的cacheKey,值为代理类的类型
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
// 存储被增强的Bean的效果,键为beanName的cacheKey,值为bool值,表示该Bean是否需要被代理,
// 如果为false,说明该Bean无需代理,true表示需要被代理
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
/**
* 由InstantiationAwareBeanPostProcessor声明
* 实例化之前调用,以决定是由Spring进行正常的实例化,还是直接被代理,如果被代理,则不需要Spring做正常
* 的实例化以及自动装配。
*/
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
/**
* 由InstantiationAwareBeanPostProcessor声明
* 在实例化之后,判定是否要对该Bean实例进行自动装配,默认都是true,即装配
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
/**
* 由BeanPostProcessor声明
* 在调用init-method方法前调用
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* 由BeanPostProcessor声明
* 在调用init-method方法后调用
* 这里是AOP的代理核心
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
@Override
@Nullable
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
if (this.proxyTypes.isEmpty()) {
return null;
}
Object cacheKey = getCacheKey(beanClass, beanName);
return this.proxyTypes.get(cacheKey);
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
//无用
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
return null;
}
//无用
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
return pvs;
}
}
概述:我们用两个场景,将所有的AOP串起来
在实例化Bean的步骤中,我们首先进入postProcessBeforeInstantiation方法,即在实例化Bean之前,给BeanPostProcessor一个机会,使得它可以代理目标对象,而不需要继续做标准的Bean实例化。
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//1.0 根据Bean的name和class,生成一个cacheKey,底层就是字符串的品专,用来标识唯一
Object cacheKey = getCacheKey(beanClass, beanName);
// 如果beanName不为空,或者beanName不为空且targetSourcedBeans这个缓存中不存在beanName对应的TargetSource记录,则进入if子句
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 如果advisedBeans中存在记录,则直接返回null,将Bean实例化的任务交给Spring去做
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 如果该类是一个基础设施类,或者该类是被skip跳过的,那么我们将其记录在advisedBeans,
// 键为beanClass,值为false,并返回null,将Bean实例化的任务交给Spring去做
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 如果存在自定义TargetSource,那么就需要在此创建代理对象,而不能将Bean实例化的任务交给Spring
// 该代码可以抑制目标bean的不必要的缺省实例化:TargetSource将以自定义的方式处理目标实例。
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
// 如果确实存在自定义的TargetSource,那么将BeanName放到targetSourcedBeans中
// 暗示这个BeanName的实例化由自定义的TargetSource来做,不由Spring处理
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 自定义代理的逻辑:
// 1.获取所有的增强器Advisor
// 2.使用自定义的targetSource,和增强器等,创建带来对象
// 3.将代理后的对象的元数据,即class对象,存到proxyTypes中,以加速
// 4.返回代理对象,并暗示Spring不要多管闲事!!
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
在一个标准的场景中,我们没有定义自定义的TargetSource,故该方法返回null,继续进入Spring的实例化Bean的流程中。
接下来,我们看postProcessAfterInitialization,它是在init-method的调用后被执行的,此时Bean实例已经完全实例化,就可以进行动态代理了~~
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
所有Aop的核心工作都基本在此。
earlyProxyReferences这个缓存变量中存储的提前代理引用,用于解决Spring中Bean循环引用。只有在被循环引用时,earlyProxyReferences中才会有数据,举个栗子:
A 依赖 B ,B 又依赖 A
我们将关注点放在wrapIfNecessary(bean,beanName,cacheKey)上:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果beanName为空,且targetSourcedBeans缓存中存在beanName对应的代理Bean,则直接返回,无需再代理
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// advisedBeans中保存的是Bean是否需要代理,如果返回False,那么明确表示不需要代理该Bean
// 具体见上面postProcessBeforeInstantiation的介绍
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 如果该bean是一个基础设施类或者是可skip的,那么将该类这种不需代理的本质记录下来并直接返回当前bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果存在可应用的增强advice,那么久为其创建代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 如果存在增强器,那么先记录该bean需代理的本质,然后为其创建代理
// 注意这里使用的targetSources是SingletonTargetSource,与自定义的TargetSource的情况不同
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;
}
概述:本方法属于Aop代理的骨架方法,拆分步骤讲解:
下面讲如何获取可应用到该Bean的增强器:
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 找到所有适合自动代理该类的Advisor。
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
// List转数组
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取所有候选Advisor,直白点讲,就是笨应用中所有的增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 获取仅对本Bean可应用的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors,
beanClass, beanName);
// 留给子类用的hook,可以注册额外的的Advisor,默认啥也不干
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 对需要代理的Advisor按照一定的规则进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
首先,获取所有候选Advisor:
protected List<Advisor> findCandidateAdvisors() {
//调用父类,以适配XML形式配置的切面进行操作,提取出所有候选的Advisor
List<Advisor> advisors = super.findCandidateAdvisors();
// 注解方式的切面操作,提取出所有候选Advisor
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
我们着重看注解方式的:
public class BeanFactoryAspectJAdvisorsBuilder {
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 调用BeanFactory,获取所有BeanDefinition的beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 循环
for (String beanName : beanNames) {
// beanName是否有效,还记得标签吗,name最终会放到includePatterns中,它们是一堆正则表达式,这里就是验证beanName是否匹配。
if (!isEligibleBean(beanName)) {
continue;
}
// 提取beanName对应的Class实例,如果无法确定Class,那么也无法代理,直接中断结束
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 如果该Class是一个Aaspect注解所标注的,那么就可以对其进行解析,以提取增强器了
if (this.advisorFactory.isAspect(beanType)) {
// 将切面的name存到缓存aspectNames中
aspectNames.add(beanName);
// 为该切面类重新建模,以AspectMetadata来维护其元数据,像@Aspect(value="perthis(...)")中的value属性,就会解析并放到元数据中保存
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// 如果切面的实例化模型是单例的,创建单例模式的工厂类BeanFactoryAspectInstanceFactory实例
// AspectInstanceFactory是用于提供AspectJ切面的实例的接口,
// 它存在的原因是为了与BeanFactory解耦
// MetadataAwareAspectInstanceFactory是AspectInstanceFactory的子接口,
// 额外添加一个新方法,即getAspectMetadata(),可以获得与@Aspect注解额类的AspectMetadata
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 获取所有的Advisor
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
// 如果Bean是单例的,那么而直接将此时解析出的Advisors缓存到advisorsCache中,否则,就将工厂缓存到aspectFactoryCache中,以备再用
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
// 切面的实例化模型并非单例,而bean却是单例的,这是违规的!!
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
// 创建Prototype的切面工厂类
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
// 代码走到这,说明缓存已经生效,也即所有的切面都已经被解析并放到了缓存中
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
// 先从advisorsCache缓存中提取切面name对应的Advisor列表,如果不存在,那么
// 可能切面并非SINGLETON的,因此aspectFactoryCache可能存在对应的工厂缓存,
// 取出MetadataAwareAspectInstanceFactory工厂,调用该工厂的getAdvisors()获取增强器
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
}
buildAspectJAdvisors方法主要是获取应用中所有的切面,并解析,缓存,概括描述:
PS:概括中对缓存的存储与提取,表达的很简单,最好看下源代码中的注释
接下来我们来看如果提取Advisors:
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取切面类的Class
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 获取切面类的名称,即beanName
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// 对方法传入的MetadataAwareAspectInstanceFactory,进行包装,使得其仅会被实例化一次
// 直白一点,就是使用包装模式,将实例化变得惰性,且单例
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
// 获取切面了中所有的可能是增强的方法,即除了@Pointcut注解的方法之外的所有方法
//拿到这所有的方法后,在调用getAdvisor(),提取出真的是增强的方法,即以@Around/@After/@Before注释的方法
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 如果该切面@Aaspect(value="")中的value属性的值不是空或者SINGLETON,那么暗示
// 它是原型实例化模式。对于这种,我们需要在最开始处(索引为0处),添加一个SyntheticInstantiationAdvisor增强器
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
//查找引介增强的属性(会单独讲)
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
// 反射获取所有的Mthod,剔除掉以@Pointcut注解的方法
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
});
methods.sort(METHOD_COMPARATOR);
return methods;
}
}
该方法中基本完全解释了如何获取Advisor,我们概述一下:
提前介绍一下Advisor,它是一个高级接口,表示一个增强器,他有多重实现,我们枚举常用的几个:
然后是Advice,它指的是增强,增强器(Advisor)是增强(Advice)和切入点(Pointcut)的聚合:
是时候看如何从切面类中解析Advisor了:
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 提取切入点
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 我们说过,Advisor是Adviuceh和pointcut的聚合,上面已经提取出了pointcut,Spring
// 将提取Advice的任务,交给了InstantiationModelAwarePointcutAdvisorImpl的构造器去做,
// 并将Advice和pointcut组合成一个Advisor,这里指的就是InstantiationModelAwarePointcutAdvisorImpl
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
//提取切入点
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 提取方法上的注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 声明一个AspectJExpressionPointcut,它表示的是一个表达式切入点,
// 类比而言,就是@Around(value = "logging()")中value属性的字符串的值,他就是表达式,也即切入点
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
// 设置其切入点的表达式
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
上面方法中解析的是切面类中的增强方法,即以@Around/@Before/@Aafter/@AterReturing/@AfterThrowing注解标注的方法。Advisor是Advice和Pointcut的聚合,先提取出Pointcut,它本质上就是一个表达式。然后将提取Advice和聚合成Advisor的工作全权交给了InstantiationModelAwarePointcutAdvisorImpl的构造器来实现的,我们追踪一下,看他是如何构造Advice的:
final class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
// 从以@Aspect注解标注的给定的类中提取出Advisor的工厂接口类
private final AspectJAdvisorFactory aspectJAdvisorFactory;
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// 如果@Aaspect(value="") value属性值是Per-xxx的,即以非单例模式实例化的切面
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// 使之动态:必须从预实例化【pre-instantiation】状态更改为后实例化【post-instantiation 】状态。
// 如果它不是一个动态切入点,那么在第一次评估之后,Spring AOP基础设施可能会对它进行优化。
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// @Aaspect(value="") value属性值是SNGLETON的,即以单例模式实例化的切面
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
// 根据给定的增强方法,即Method,获得一个对应的Advisor
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
}
InstantiationModelAwarePointcutAdvisorImpl中只是一个实例化与聚合的骨架,并针对切面的实例化模式,实行不同的逻辑。
我们以切面单例实例化模式来讲,它将Advice的工作委托给instantiateAdvice(pointcut)方法,而该方法有委托给AspectJAdvisorFactory对象来做的,基础实现只有一个,即ReflectiveAspectJAdvisorFactory,该工厂的作用即使通过发射,将增强的Method转换为一个Advice:
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 获取方法上的切面注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 校验下方法所属的类是否以@Aaspect标注
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
// 工厂模式,根据不同的注解类型,生成不同的Advice实例
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// 配置Advice
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
越深入,越简单,一个简单工厂实现罢了。
方法增强解析完了,我们来看引介增强~~
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
...其他省略了...
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
...其他省略了...
}
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
if (declareParents == null) {
// Not an introduction field
return null;
}
if (DeclareParents.class == declareParents.defaultImpl()) {
throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
}
return new DeclareParentsAdvisor(
introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}
引增强的转换很简单,因为引介只能发生在属性上,因此提取出所有的Field,然后循环。提取出属性上的注解,如果存在@DeclareParents注解,那么它确实是引介增强,那么实例化一个DeclareParentsAdvisor,作为该引介增强的Advisor实现。
具体的对象构造就不看了,举个引介增强使用的例子,大家就懂了:
##TODO
提取出应用中所有的Advisor,我们来看如何找到可应用于该Bean的Advisor:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//上面讲的
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 接下来讲的
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
我们看到底如何做的:
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
// ProxyCreationContext向ThreadLocal变量中设置当前处理的beanName,并在finally字句中移除掉
// 因为是ThreadLocal是线程级的,而创建过程不涉及多线程,没什么安全问题
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
重点代码是:AopUtils.findAdvisorsThatCanApply,即从所有Advisors中找出适合应用到本Bean的Advisors
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
// 合格的增强器列表
List<Advisor> eligibleAdvisors = new ArrayList<>();
// 优先处理引介增强
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
// 如果该Advisor已经在上面引介增强中处理过,那么就continue下一条
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 处理方法增强以及同步增强(SyntheticInstantiationAdvisor)
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
//判定该Advisor是否对该Bean可应用
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
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;
}
}
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;
}
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;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
一些列的正则匹配,最终确定是否可以将该Advisor应用到该Bean实例上。
可应用的Aadvisors已经全部提取出来了,现在就是最后一步了,创建代理:
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 构建ProxyFactory,它是工具类,专门来生成代理的
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 判断当前proxyFactory是否设置了proxy-target-class = true,如果true,那么etProxyTargetClass(true),
// 这会强制Spring在创建代理时使用CGLib动态代理
// 而如果未设置,则调用evaluateProxyInterfaces()方法,评估是否存在父接口
// 存在,则将其设置仅proxyFactory,如果不存在,则依然使用CGLib
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 将给定的specificInterceptors,包装转换为Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
// 如果待代理的类有接口,那addInterface()将其设置进proxyFactory
// 否则,依然setProxyTargetClass(true)设置使用CGLib代理
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
proxyFactory.setProxyTargetClass(true);
}
}
}
该方法主要的两行代码,分别是:
我们分别讲解,先是buildAdvisor(…)
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// 缺省情况下没有公共拦截器,或者所公共Aadvisor的
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
// 如果commonInterceptors的长度大于0,那么需要与传入的specificInterceptors进行merge
if (commonInterceptors.length > 0) {
// 如果设置为优先应用公共Advisor,则将commonInterceptors放到索引0处
// 否则添加到尾部
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 对Advisor包装,原地修改
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
构建Advisor,首先获取所有公共的Advisor,默认是没有的。然后将传入的specificInterceptors与刚解析出的commonInterceptors进行merge。最后则是进行wrap,最终均转换为Advisor,下面给出包装逻辑,其实很简单:
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
* Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
*/
public DefaultAdvisorAdapterRegistry() {
//如果传入的Advice是MethodBeforeAdvice,那么可适配
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
//如果传入的Advice是AfterReturningAdvice,那么可适配
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
//如果传入的Advice是ThrowsAdvice,那么可适配
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
//包装,该方法结束后,传入的adviceObject都会被转成Advisor,否则报错
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 1.0 如果本来就是SAdvisor,则直接返回
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 2.0 如果到这里,确定它不是一个Advice,那么抛出异常
// spring要求进到这个方法时,要么是Advice,要么是Advisor
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
// 强制转换
Advice advice = (Advice) adviceObject;
// 如果该Advice是一个拦截器MethodInterceptor类型,那么用DefaultPointcutAdvisor封装它
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
// 如果Advice并不是一个MethodInterceptor,那么使用本类固定的三个适配器,判断是否可适配
// 如果可适配,则用DefaultPointcutAdvisor包装它,否则抛出异常
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
}
获取了所有Advisors,下面就是创建代理这最后临门一脚了:
public class ProxyCreatorSupport extends AdvisedSupport {
private AopProxyFactory aopProxyFactory;
/**
* Create a new ProxyCreatorSupport instance.
*/
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
/**
* Create a new ProxyCreatorSupport instance.
* @param aopProxyFactory the AopProxyFactory to use
*/
public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
this.aopProxyFactory = aopProxyFactory;
}
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
}
构建AopProxy的实现是在DefaultAopProxyFactory中实现的:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
/**
* 根据配置,确定使用哪个实现,到底是JdkDynamicAopProxy还是ObjenesisCglibAopProxy作为AopProxy的实例
*/
@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);
}
}
}
通过这if条件语句,我们可以总结出Spring选取AopProxy实现的逻辑:
Finally,创建代理,AopProxy.getProxy,有点复杂,直接看invoke方法:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
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;
// 如果需要在目标对象内获取对代理对象的感知,那么需要设置CurrentProxy属性为代理对象
// 这样我们可以通过AopContext.getCurrentProxy()获取到当前被代理的类的代理类。
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 从传给AopProxy的TargetSource中取出目标对象,即原始的对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取该方法的拦截器链,其实是Advisor转换的
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 看看有没有什么增强。如果不没有,我们可以退回到对目标方法的直接反射调用,并避免创建方法调用【MethodInvocation】
if (chain.isEmpty()) {
// 如果没有拦截器链,那么直接调用切点方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 如果有拦截器链,构建一个方法调用抽象,并通过拦截器链进入到连接点【Pointcut】
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 执行拦截器链
retVal = invocation.proceed();
}
// 返回结果
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
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);
}
}
}
}
首先看一下TargetSource的定义:
public interface TargetClassAware {
/**
* Return the target class behind the implementing object
* (typically a proxy configuration or an actual proxy).
* @return the target Class, or {@code null} if not known
*/
@Nullable
Class<?> getTargetClass();
}
public interface TargetSource extends TargetClassAware {
/**
* 返回目标类型的Class实例
* @return the type of targets returned by this {@link TargetSource}
*/
@Override
@Nullable
Class<?> getTargetClass();
/**
* 如果是静态的,那么getTarget()返回的就是相同的对象,否则,返回的不一定是一样的对象
* In that case, there will be no need to invoke {@link #releaseTarget(Object)},
* and the AOP framework can cache the return value of {@link #getTarget()}.
* @return {@code true} if the target is immutable
* @see #getTarget
*/
boolean isStatic();
/**
* 返回一个目标实例。在AOP代理的目标方法被调用时,会从targetSource中提取出目标对象,即原始对象。
* @return the target object which contains the joinpoint,
* or {@code null} if there is no actual target instance
* @throws Exception if the target object can't be resolved
*/
@Nullable
Object getTarget() throws Exception;
/**
* 释放由getTarget()方法返回的目标对象。
* Spring在完目标bean之后会调用这个方法释放目标bean对象,对于一些需要池化的对象,这个方法是必须
* 要实现的,这个方法默认不进行任何处理
*/
void releaseTarget(Object target) throws Exception;
}
看一下Spring官方提供的几个实现:
首先看简单的SingletonTargetSource,他也是我们最常用到的TargetSource:
public class SingletonTargetSource implements TargetSource, Serializable {
/** use serialVersionUID from Spring 1.2 for interoperability. */
private static final long serialVersionUID = 9031246629662423738L;
/** 缓存目标对象 */
private final Object target;
/**
* 根据给定的目标对象,创建一个SingletonTargetSource
* @param target the target object
*/
public SingletonTargetSource(Object target) {
Assert.notNull(target, "Target object must not be null");
this.target = target;
}
@Override
public Class<?> getTargetClass() {
return this.target.getClass();
}
// 返回目对象
@Override
public Object getTarget() {
return this.target;
}
@Override
public void releaseTarget(Object target) {
// nothing to do
}
// 静态的,因此多次调用getTarget()都返回同一个目标对象
@Override
public boolean isStatic() {
return true;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof SingletonTargetSource)) {
return false;
}
SingletonTargetSource otherTargetSource = (SingletonTargetSource) other;
return this.target.equals(otherTargetSource.target);
}
/**
* SingletonTargetSource uses the hash code of the target object.
*/
@Override
public int hashCode() {
return this.target.hashCode();
}
@Override
public String toString() {
return "SingletonTargetSource for target object [" + ObjectUtils.identityToString(this.target) + "]";
}
}
SingletonTargetSource是我们在Aop中最常用的TargetSource实现,它提供了对目标对象的缓存,亦即我们在同一个代理对象中,调用多次aop方法,那么都是在同一个目标对象(即原始对象)上操作。
接下来看一个比较特殊的TargetSource,它是CommonsPool2TargetSource,它实现了池化:
public class CommonsPool2TargetSource extends AbstractPoolingTargetSource implements PooledObjectFactory<Object> {
private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
private long maxWait = GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS;
private long timeBetweenEvictionRunsMillis = GenericObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
private long minEvictableIdleTimeMillis = GenericObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private boolean blockWhenExhausted = GenericObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
/**
* Apache Commons 包的ObjectPool.
*/
@Nullable
private ObjectPool pool;
/**
* 创建一个CommonsPoolTargetSource,使用默认配置
* 默认池的最大大小为8。
* @see #setMaxSize
* @see GenericObjectPoolConfig#setMaxTotal
*/
public CommonsPool2TargetSource() {
setMaxSize(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL);
}
/**
* 设置池中允许的空闲对象的最大数量,默认8
* @see GenericObjectPool#setMaxIdle
*/
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
/**
* 返回池中允许的空闲对象的最大数量。
*/
public int getMaxIdle() {
return this.maxIdle;
}
/**
* 设置池中空闲对象的最小数量。默认是0
* @see GenericObjectPool#setMinIdle
*/
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
/**
* 返回池中所允许的空闲对象的最小数量。
*/
public int getMinIdle() {
return this.minIdle;
}
/**
* 设置从池中获取对象的最大等待时间,默认-1,即一直等待
* @see GenericObjectPool#setMaxWaitMillis
*/
public void setMaxWait(long maxWait) {
this.maxWait = maxWait;
}
/**
* 返回从池中获取对象的最大等待时间。
*/
public long getMaxWait() {
return this.maxWait;
}
/**
* Set the time between eviction runs that check idle objects whether they have been idle for too long or have become invalid.
* Default is -1, not performing any eviction.
* @see GenericObjectPool#setTimeBetweenEvictionRunsMillis
*/
public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
}
/**
* Return the time between eviction runs that check idle objects.
*/
public long getTimeBetweenEvictionRunsMillis() {
return this.timeBetweenEvictionRunsMillis;
}
/**
* 设置空闲对象在被驱逐之前可以驻留在池中的最小时间。默认值为1800000(30分钟)。
* 请注意,需要执行清除操作才能使此设置生效。
* @see #setTimeBetweenEvictionRunsMillis
* @see GenericObjectPool#setMinEvictableIdleTimeMillis
*/
public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
/**
* 返回空闲对象可以驻留在池中的最小时间。
*/
public long getMinEvictableIdleTimeMillis() {
return this.minEvictableIdleTimeMillis;
}
/**
* 设置当池耗尽时调用是否应该停止。
*/
public void setBlockWhenExhausted(boolean blockWhenExhausted) {
this.blockWhenExhausted = blockWhenExhausted;
}
/**
* 当池耗尽时调用是否应该阻塞。
*/
public boolean isBlockWhenExhausted() {
return this.blockWhenExhausted;
}
/**
* 创建并持有一个ObjectPool
* @see #createObjectPool()
*/
@Override
protected final void createPool() {
logger.debug("Creating Commons object pool");
this.pool = createObjectPool();
}
/**
* 如果子类想要返回特定的对象池,则可以覆盖此属性。
* @return an empty Commons {@code ObjectPool}.
* @see GenericObjectPool
* @see #setMaxSize
*/
protected ObjectPool createObjectPool() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(getMaxSize());
config.setMaxIdle(getMaxIdle());
config.setMinIdle(getMinIdle());
config.setMaxWaitMillis(getMaxWait());
config.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
config.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
config.setBlockWhenExhausted(isBlockWhenExhausted());
return new GenericObjectPool(this, config);
}
/**
* 从ObjectPool中借调对象
*/
@Override
public Object getTarget() throws Exception {
Assert.state(this.pool != null, "No Commons ObjectPool available");
return this.pool.borrowObject();
}
/**
* Returns the specified object to the underlying {@code ObjectPool}.
*/
@Override
public void releaseTarget(Object target) throws Exception {
if (this.pool != null) {
this.pool.returnObject(target);
}
}
@Override
public int getActiveCount() throws UnsupportedOperationException {
return (this.pool != null ? this.pool.getNumActive() : 0);
}
@Override
public int getIdleCount() throws UnsupportedOperationException {
return (this.pool != null ? this.pool.getNumIdle() : 0);
}
/**
* Closes the underlying {@code ObjectPool} when destroying this object.
*/
@Override
public void destroy() throws Exception {
if (this.pool != null) {
logger.debug("Closing Commons ObjectPool");
this.pool.close();
}
}
//----------------------------------------------------------------------------
// Implementation of org.apache.commons.pool2.PooledObjectFactory interface
//----------------------------------------------------------------------------
@Override
public PooledObject<Object> makeObject() throws Exception {
return new DefaultPooledObject<>(newPrototypeInstance());
}
@Override
public void destroyObject(PooledObject<Object> p) throws Exception {
destroyPrototypeInstance(p.getObject());
}
@Override
public boolean validateObject(PooledObject<Object> p) {
return true;
}
@Override
public void activateObject(PooledObject<Object> p) throws Exception {
}
@Override
public void passivateObject(PooledObject<Object> p) throws Exception {
}
}
CommonsPool2TargetSource实现非常简单的,其将主要功能都委托给了ObjectPool进行,ApacheCommon包提供的实现。通俗的讲,就是AopProxy在getTarget()时,从ObjectPool借调一个对象,用完之后再归还。
那么自定义TargetSource实在什么时候生效呢呢?其实是在Bean实例化之前,调用InstantiationAwareBeanPostProcessor(BeanPostProcess的子接口)所声明的postProcessBeforeInstantiation()方法中做的,我们来看一下由< aop:aspectj-autoproxy> 引入的AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor,在postProcessBeforeInstantiation()到底是如何做的:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 获取自定义TargetSource,并使用该TargetSource,生成代理
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
postProcessBeforeInstantiation()是在Bean真正实例化前,Spring给BeanPosProcesosr一个机会,让其决定是否可以对该Bean应用代理(自定义代理),如果该方法的返回值不为null,那么说明该Bean被代理了,也就不需要继续由Spring实例化了,只需要再依次为该代理的Bean应用postProcessAfterInitialization()即可。
自定义TargetSource与非自定义的TargetSource,在代理的处理逻辑上基本一致,先获取可以应用于该Bean的Advisors列表,然后根据Advisors、TargetSource、beanName、beanClass为目标Bean创建代理。
那么TargetSource的getTarget()还有releaseTarget()到底是什么时候调用的?我们来看AopProxy的JDK实现,即JdkDynamicAopProxy,在他的invoke方法中,有这样的一段骨架代码:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取资源,这在池化的TargetSource中很重要
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// 返回值
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && 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()) {
// 调用releaseTarget释放资源
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
概述:在真正执行目标方法前,通过调用传入给AopProxy的TargetSource的getTarget()方法获取到目标对象(即原始对象),然后调用代理的目标方法,在finally中最终调用releaseTarget(…)释放目标资源,在池化场景中,即将对象归还给ObjectPool