ScopedFactoryBean入门级解析

来源:互联网 发布:2016网络最火的神曲 编辑:程序博客网 时间:2024/06/05 10:15

scopedFactoryBean

根据scope的注解属性,判断是否需要scoped代理

    static BeanDefinitionHolder applyScopedProxyMode(            ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {        // 获取@scope的proxyMode属性        ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();        // 如果此类不需要代理,默认是不需要的代理的        if (scopedProxyMode.equals(ScopedProxyMode.NO)) {            return definition;        }        // 如果需要cglib代理        boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);        // 返回被代理后的beanDefinition        return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);    }

具体实现是
org.springframework.aop.scope.ScopedProxyUtils.createScopedProxy()

    public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,            BeanDefinitionRegistry registry, boolean proxyTargetClass) {        String originalBeanName = definition.getBeanName();        BeanDefinition targetDefinition = definition.getBeanDefinition();        // 生成代理bean的名称,就是在前面加上"scopedTarget"前缀        String targetBeanName = getTargetBeanName(originalBeanName);        // Create a scoped proxy definition for the original bean name,        // "hiding" the target bean in an internal target definition.        // 创建一个scope级别的BeanDefinition        RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);        proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));        proxyDefinition.setOriginatingBeanDefinition(targetDefinition);        proxyDefinition.setSource(definition.getSource());        proxyDefinition.setRole(targetDefinition.getRole());        proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);        if (proxyTargetClass) {            targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);            // ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.            // 不需要在这里明确的设置,因为默认是true        }        else {            proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);        }        // Copy autowire settings from original bean definition.        // 从源bean定义中拷贝自动装配的配置        proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());        // 是否按照默认的策略进行装配        proxyDefinition.setPrimary(targetDefinition.isPrimary());        if (targetDefinition instanceof AbstractBeanDefinition) {            // 拷贝qualifiers的配置            proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);        }        // The target bean should be ignored in favor of the scoped proxy.        // 设置源bean在其它bean依赖于它的时候,不被作为一个候选项,因为需要放进去的是一个scoped的代理bean        targetDefinition.setAutowireCandidate(false);        // 当然也不按照默认的策略填充它        targetDefinition.setPrimary(false);        // Register the target bean as separate bean in the factory.        // 注册源beandefine        registry.registerBeanDefinition(targetBeanName, targetDefinition);        // Return the scoped proxy definition as primary bean definition        // (potentially an inner bean).        // 现在返回替换为代理bean的holder        return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());    }

这是BeanDefine实现完成了
在真正的实例化的时候,这个bean会返回一个特殊的代理,
为什么特殊呢,别的代理都是代理同一个bean,但是这个代理牛逼,只是存一下代理的类的信息,每一次都去beanfactory去取。
如果bean的scope是prototype,当然每一次beanfactory都会创建新的bean
如果bean是单例的,当然返回容器缓存的bean。
他是怎么是实现的呢?
在getObject()的时候,从beanfactory去取。。详细看下面源码
org.springframework.aop.scope.ScopedProxyFactoryBean

会先设置BeanFactory

    public void setBeanFactory(BeanFactory beanFactory) {        if (!(beanFactory instanceof ConfigurableBeanFactory)) {            throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);        }        ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;        this.scopedTargetSource.setBeanFactory(beanFactory);        ProxyFactory pf = new ProxyFactory();        pf.copyFrom(this);        //这个这个代理Bean设置Bean的来源,很重要。这个方法决定了,        //每次取target的时候,都会调用beanFactory.getBean,所以scope为prototype的时候,可以正确的每一次都是新的实例        // 因为是SimpleBeanTargetSource        pf.setTargetSource(this.scopedTargetSource);        Class<?> beanType = beanFactory.getType(this.targetBeanName);        // 如果工厂里面没有此类的定义        if (beanType == null) {            throw new IllegalStateException("Cannot create scoped proxy for bean '" + this.targetBeanName +                    "': Target type could not be determined at the time of proxy creation.");        }        if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {            pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));        }        // Add an introduction that implements only the methods on ScopedObject.        // 构建一个introduction,这个introduction只实现了ScopedObject的所有接口        ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());        pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));        // Add the AopInfrastructureBean marker to indicate that the scoped proxy        // itself is not subject to auto-proxying! Only its target bean is.        //将scopedObject作为通知加入到proxy中,DelegatingIntroductionInterceptor作为通知的拦截器,        //实际上是使得所有在proxyBean上调用的'getTargetObject`方法都被代理到了`DefaultScopedObject`中。        //在增加通知的同时会生成DefaultIntroductionAdvisor 作为advisor,        pf.addInterface(AopInfrastructureBean.class);        this.proxy = pf.getProxy(cbf.getBeanClassLoader());    }

org.springframework.aop.scope.DefaultScopedObject

        /**     *  就是这里 ,每一次调用被注入实例的时候都从工厂中获取     * @return 根据scope的类型由工厂是否返回新的实例     */    @Override    public Object getTargetObject() {        return this.beanFactory.getBean(this.targetBeanName);    }
原创粉丝点击