1. Spring AOP示例代码
示例代码结构如下图所示:
其中切面类AspectObject
的代码:
@Aspect
@Component
public class AspectObject {
//抽取公共的切入点表达式
//1、本类引用
//2、其他的切面引用
@Pointcut("execution(public * io.zgc.spring.features.aop.annotation.TargetObject.*(..))")
public void pointCut(){};
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+ Arrays.asList(args)+"}");
}
@After("io.zgc.spring.features.aop.annotation.AspectObject.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
}
被代理类TargetObject
的代码:
@Component
public class TargetObject implements TargetInterface{
public String sayHello(String name) {
System.out.println("hello,"+name);
return "hello---"+name;
}
}
测试客户端Client
的代码:
package io.zgc.spring.features.aop.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Client {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
TargetInterface bean = applicationContext.getBean(TargetInterface.class);
bean.sayHello("zgc");
System.out.println(bean.getClass().getName());
}
}
运行测试代码,输入如下结果
sayHello运行。。。@Before:参数列表是:{[zgc]}
hello,zgc
sayHello结束。。。@After
sayHello正常返回。。。@AfterReturning:运行结果:{hello---zgc}
com.sun.proxy.$Proxy21
从输出结果,可以看出TargetObject
类,已经被Spring
修改成了代理类com.sun.proxy.$Proxy21
并在sayHello
方法执行的织入了代理逻辑。接下来,我们就来分析下Spring
是在什么地方以及通过什么方式将TargetObject
替换成代理对象。
2. Debug调试
我们使用倒推的方式进行debug,重点关注我们需要关注的代码。
2.1. getBean调试
我们先假设代理对象实在获取bean
的时候发生的。
TargetInterface bean = applicationContext.getBean(TargetInterface.class);
Debug
跟进去发现,它最终是在singletonObjects
中将代理对象获取出来的,而singletonObjects
是个Map结构,它里面存放的是单例bean
,可以简单将其理解为bean
工厂(tips:这种理解并不准确)。
这里我们可以得出结论:代理对象的创建一定是包含在ApplicationContext对象创建的过程中。
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
那我们就在singletonObjects
放置值的地方加上断点,再通过程序的调用栈尝试查看代理对象在什么地方生成。
为了减低干扰,断点需要加上条件beanName.equals("targetObject");
2.2. ApplicationContext创建debug
上面断点设置后,我们重新运行程序,可以看到以下程序调用栈
我们向上追溯一下调用栈上的代码,调用addSingleton()
方法时已经将代理对象通过入参传递进来。而DefaultSingletonBeanRegistry#getSingleton()
的伪代码如下:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
... ...
try {
// 这里获取targetObject的代理对象,实际会调用createBean方法
singletonObject = singletonFactory.getObject();
}
... ...
addSingleton(beanName, singletonObject);
}
return singletonObject;
}
}
继续向上追溯, AbstractBeanFactory#doGetBean
, 其伪代码如下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
... ...
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
return (T) bean;
}
结合getSingleton
和doGetBean
方法可知,当调用ObjectFactory
的getObject
方法时,会触发ObjectFactory
类的createBean
方法执行。
至此,我们知道了代理对象的创建是发生在createBean
方法中,因此我们在此处增加条件断点,看看spring
在createBean
方法中做了哪些操作。
2.3. createBean调试
设置好断点之后,我们重新执行程序,一路step into
。
图中最下面的lambda$doGetBean
就是我们给createBean
设置断点的地方。最终程序执行到了AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
。其代码如下:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
可以看到这里是遍历所有的BeanPostProcessor
,然后依次执行其postProcessAfterInitialization
方法。此时Spring
运行的相关变量如下
这里注意一下,程序运行到这里,TargetObject
对应的是原始对象,还没有被代理。
另外当前Spring
上下文中包含的BeanPostProcessor
中,有一个AnnotationAwareAspectJAutoProxyCreator
。这个类是个后置处理器,它和代理对象的创建密不可分。
2.4. AnnotationAwareAspectJAutoProxyCreator调试
我们先来看看AnnotationAwareAspectJAutoProxyCreator
类的继承结构
可以看到AnnotationAwareAspectJAutoProxyCreator
类继承了BeanPostProcessor
和BeanFactoryAware
。而BeanFactoryAware
接口的postProcessAfterInitialization
方法是在父类AbstractAutoProxyCreator
中实现。
下面接着上面的applyBeanPostProcessors
方法继续调试。
最终请求链路进入到ProxyCreatorSupport#createAopProxy
方法(接下来的代码都是创建aop代理对象的核心逻辑),其源码如下:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory#createAopProxy
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);
}
}
最终调用JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
方法,其内部同步JDK
动态代理,创建代理对象。
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
至此,我们已经清楚的知道Spring
是如何创建AOP
代理对象。
2.5. 小结
Spring
在创建IOC
容器时,通过Spring
提供的后置处理器扩展点,先向容器注册一个AnnotationAwareAspectJAutoProxyCreator
后置处理器。再通过该后置处理器(其他后置处理器也如此)可以介入bean
创建的生命周期,将原生bean
通过JDK
动态代理和cglib
的方式替换成AOP
代理类。
3. @EnableAspectJAutoProxy
上面还有一个疑问,AnnotationAwareAspectJAutoProxyCreator
是怎么注册到IOC
容器中的?答案就是@EnableAspectJAutoProxy
。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
可以看到在@EnableAspectJAutoProxy
注解中,为引入了(向容器注册)AspectJAutoProxyRegistrar
类。
@Import(AspectJAutoProxyRegistrar.class)
AspectJAutoProxyRegistrar
类最终会引入AnnotationAwareAspectJAutoProxyCreator
后置处理器,相关代码如下:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
AopConfigUtils
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
注册AnnotationAwareAspectJAutoProxyCreator
的代码最终是需要创建IOC
容器时来触发,调用链路图如下:
3.1. 创建和注册AnnotationAwareAspectJAutoProxyCreator流程
流程:
1)、传入配置类(或者配置文件),创建ioc容器
2)、注册配置类,调用refresh()刷新容器;
3)、registerBeanPostProcessors(beanFactory);注册bean的后置处理器来方便拦截bean的创建;
AnnotationAwareAspectJAutoProxyCreator创建时序图
1、先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
2、给容器中加别的BeanPostProcessor
3、优先注册实现了PriorityOrdered接口的BeanPostProcessor;
4、再给容器中注册实现了Ordered接口的BeanPostProcessor;
5、注册没实现优先级接口的BeanPostProcessor;
6、注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中;创建internalAutoProxyCreator BeanPostProcessor 【 AnnotationAwareAspectJAutoProxyCreator 】
- 6.1. 创建Bean的实例
- 6.2. populateBean;给bean的各种属性赋值
- 6.3. initializeBean:初始化bean;
- 6.3.1. invokeAwareMethods():处理Aware接口的方法回调
- 6.3.2. applyBeanPostProcessorsBeforeInitialization():应用后置处理器的postProcessBeforeInitialization()
- 6.3.3. invokeInitMethods();执行自定义的初始化方法
- 6.3.4. applyBeanPostProcessorsAfterInitialization();执行后置处理器的postProcessAfterInitialization();
- 6.4. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;--》aspectJAdvisorsBuilder
- 把BeanPostProcessor注册到BeanFactory中;
beanFactory.addBeanPostProcessor(postProcessor);
网友评论