Blog

  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

SpringAop------代理对象的创建(一)

发表于 2019-08-10 更新于 2019-08-11 阅读次数:
本文字数: 8.8k

简介

了解一下Aop中的目标对象和代理对象

测试代码(切面类和测试类在之前的aop基本使用中)

1
2
3
4
5
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.yb");
SpringAopTest springaoptest = (SpringAopTest) context.getBean(SpringAopTest.class);
}

首先,将@EnableAspectJAutoProxy注解注释掉,调试一下。

然后,加上@EnableAspectJAutoProxy注解,调试一下。

那么上面的就是目标对象,下面的就是代理对象。那么接下来就在调试中去探索一下这个代理对象是如何产生。

源码调试

1
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.yb");

这行代码,了解spring的应该都是知道是用来初始化ioc容器,里面有个beanFactory,其中有个叫SingletonObjects,也就是所谓的单例池,里面就是保存所有的单例bean对象。其本质就是一个map,当我们调用getBean()时,就是从这个map中去查找,那么既然有get,那么肯定在实例化bean的时候有个,put的方法将这个bean放到这个map中。那么就查找一个是否存在一个SingletonObjects.put()这个方法。(ctrl+shift+f)全局查找,结果如下:

,根据方法名和参数,可以判断是第一个。
1
2
3
4
5
6
7
8
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

此时,我们在this.singletonObjects.put(beanName, singletonObject);出打个断点,并且加上断点条件————“springAopTest”.equals(beanName)(否则其他不相干的bean也会调用此方法),重新开始调试。

从上面的可以发现,此时的springAopTest确实已经是代理对象了,那么可以根据方法调用栈一步一步往前找。

getSingleton(其他本次调试无关的我都删了昂)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}

当执行完Object singletonObject = this.singletonObjects.get(beanName);时,可发现此时singletonObject是null,说明此时的singletonObjects中没有代理对象的(此时肯定没有啊,因为都没有调用put方法,哈哈哈哈),继续,当执行完singletonObject = singletonFactory.getObject();后,发现,此时代理对象出现了。那么继续看看这个singletonFactory.getObject()方法。

doGetBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//......
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//......
return (T) bean;
}

这里的getSinleton(beanName,()->{}),里面是个Lambda表达式代替的匿名类

1
2
3
4
5
6
new ObjectFactory(){
@override
getObject(){
//...
}
}

看这名字creatbean,感觉应该是在这里没错了。调试一下看看

createBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

//......
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}

try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException ex) {
// A previously detected exception with proper bean creation context already...
throw ex;
}
catch (ImplicitlyAppearedSingletonException ex) {
// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

看下 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 上的注释:// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.给BeanPostProcessors(后置处理器)一个机会来返回一个代理对象代替目标对象。感觉好像是在这里生成代理对象的,但是执行之后发现bean居然是null,怎么肥四,就先继续往下走叭,当走到 Object beanInstance = doCreateBean(beanName, mbdToUse, args);时,发现代理对象出现了。

doGetBean (和之前的那个不一样)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
return exposedObject;
}

instanceWrapper = createBeanInstance(beanName, mbd, args);这里创建了目标对象实例,instanceWrapper.getWrappedInstance()获取目标对象,一直到 exposedObject = initializeBean(beanName, exposedObject, mbd);这里才出现了代理对象。

initializeBean

1
2
3
4
5
6
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}

执行了applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)后出现了代理对象

applyBeanPostProcessorsAfterInitialization

1
2
3
4
5
6
7
8
9
10
11
12
13
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

这个方法里主要是遍历后置处理器。并且执行其中的postProcessAfterInitialization方法,其中有很多的后置处理器,到底执行的是哪一个呢?(查了一下是AnnotationAwareAspectJAutoProxyCreator这个后置处理器)
它是从@EnableAspectJAutoProxy中@Import(AspectJAutoProxyRegistrar.class),其中有个registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);的方法

这里可以发现AnnotationAwareAspectJAutoProxyCreator确实是一个后置处理器。发现这个类中并没有postProcessAfterInitialization方法,然后在其父类(AbstractAutoProxyCreator)中找到了

1
2
3
4
5
6
7
8
9
public Object postProcessAfterInitialization(@Nullable 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;
}

进入此方法中,发现其中有个createProxy方法,代理对象就是在这里创建的

1
2
3
4
5
6
7
8
9
// Create proxy if we have advice.
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;
}

------ 已触及底线感谢您的阅读 ------
麻辣香锅不要辣 微信支付

微信支付

  • 本文作者: 麻辣香锅不要辣
  • 本文链接: https://http://ybhub.gitee.io/2019/08/10/SpringAop-proxy/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
# SpringAop
SpringAop
SpringAop------代理对象的创建(二)
  • 文章目录
  • 站点概览
麻辣香锅不要辣

麻辣香锅不要辣

21 日志
11 分类
20 标签
GitHub 简书
  1. 1. 简介
  2. 2. 测试代码(切面类和测试类在之前的aop基本使用中)
  3. 3. 源码调试
    1. 3.1. getSingleton(其他本次调试无关的我都删了昂)
    2. 3.2. doGetBean
    3. 3.3. createBean
    4. 3.4. doGetBean (和之前的那个不一样)
    5. 3.5. initializeBean
    6. 3.6. applyBeanPostProcessorsAfterInitialization
© 2019 – 2020 麻辣香锅不要辣 | 站点总字数: 20.4k字
|
0%