@RefreshScope 和 @Scope的使用及源码解析

文章详细介绍了Spring框架中@Scope注解的用法,包括singleton、prototype等作用域,以及proxyMode参数的作用。在@Scope(prototype)时,如何通过proxyMode配置实现每次注入新的bean实例。此外,文章还探讨了@RefreshScope注解,它是如何扩展作用域并在应用刷新时重新创建bean的。
摘要由CSDN通过智能技术生成

一、@Scope

@Scope 是用来定义Spring Bean的作用域范围。分为singleton、prototype、request、session、application等。其中singleton和prototype为bean对象单例和每次都创建,其余的为scope的扩展。spring中自带request、session、application。主要是通过map对象存储。在spring创建bean中的代码如下:

               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);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}

 这个scopes在spring初始化的时候创建,在refresh()方法的postProcessBeanFactory(beanFactory);中GenericWebApplicationContext.postProcessBeanFactory方法

    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        if (this.servletContext != null) {
            beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
            beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        }

        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
    }
    public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, @Nullable ServletContext sc) {
        beanFactory.registerScope("request", new RequestScope());
        beanFactory.registerScope("session", new SessionScope());
        if (sc != null) {
            ServletContextScope appScope = new ServletContextScope(sc);
            beanFactory.registerScope("application", appScope);
            sc.setAttribute(ServletContextScope.class.getName(), appScope);
        }

        beanFactory.registerResolvableDependency(ServletRequest.class, new WebApplicationContextUtils.RequestObjectFactory());
        beanFactory.registerResolvableDependency(ServletResponse.class, new WebApplicationContextUtils.ResponseObjectFactory());
        beanFactory.registerResolvableDependency(HttpSession.class, new WebApplicationContextUtils.SessionObjectFactory());
        beanFactory.registerResolvableDependency(WebRequest.class, new WebApplicationContextUtils.WebRequestObjectFactory());
        if (jsfPresent) {
            WebApplicationContextUtils.FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
        }

    }
	public void registerScope(String scopeName, Scope scope) {
		Assert.notNull(scopeName, "Scope identifier must not be null");
		Assert.notNull(scope, "Scope must not be null");
		if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
			throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
		}
		Scope previous = this.scopes.put(scopeName, scope);
		if (previous != null && previous != scope) {
			if (logger.isDebugEnabled()) {
				logger.debug("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]");
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Registering scope '" + scopeName + "' with implementation [" + scope + "]");
			}
		}
	}

 @Scope注解在使用时,需要定义value,内容如果不是自己扩展的话,只能定义为singleton、prototype、request、session、application。

同时还有一个proxyMode的参数,默认为DEFAULT,还有INTERFACES、TARGET_CLASS两种。interfaces主要使用jdk的动态代理,target_class使用cglib代理。

proxyMode参数主要是用在以下这种情况

@Component
public class BeanA {
    @Autowired
    private BeanB beanB;

    public void printB(){
        System.out.println(beanB);
    }
}
@Component
@Scope("prototype")
public class BeanB {
}
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext an = new AnnotationConfigApplicationContext();
        an.scan("lookup.test");
        an.refresh();

        BeanA beanA = (BeanA)an.getBean("beanA");
        beanA.printB();
        beanA.printB();
    }
}

结果:

 可以看到,即使BeanB写了每次创建,在注入到BeanA的时候,也是默认单例。那如何实现需求,可以将BeanB的注解改一下

@Component
@Scope(value = "prototype",proxyMode = ScopedProxyMode.TARGET_CLASS)
public class BeanB {
}

再执行一次,看结果:

 可以看到已经实现了不同的BeanB对象注入到BeanA中。

二、源码解析

在springboot或者spring加载扫描bean对象时,会通过ClassPathBeanDefinitionScanner的doScan方法。

	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

该方法在扫描标有@Component对象后,会执行this.scopeMetadataResolver.resolveScopeMetadata(candidate)方法

	public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
		ScopeMetadata metadata = new ScopeMetadata();
		if (definition instanceof AnnotatedBeanDefinition) {
			AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
					annDef.getMetadata(), this.scopeAnnotationType);
			if (attributes != null) {
				metadata.setScopeName(attributes.getString("value"));
				ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
				if (proxyMode == ScopedProxyMode.DEFAULT) {
					proxyMode = this.defaultProxyMode;
				}
				metadata.setScopedProxyMode(proxyMode);
			}
		}
		return metadata;
	}

该方法会获取@Scope注解中的proxyMode值,并set到metadata中。默认为No。之后会执行doScan方法中的 AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry)方法。

	static BeanDefinitionHolder applyScopedProxyMode(
			ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

		ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
		if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
			return definition;
		}
		boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
		return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
	}

	public static BeanDefinitionHolder createScopedProxy(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {

		return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
	}

如果不使用动态代理,则直接返回,否则判断使用interface或是targetclass哪种。就是jdk和cglib两种代理的区别。示例中我们使用的cglib。之后进入ScopedProxyUtils.createScopedProxy方法。

	public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
			BeanDefinitionRegistry registry, boolean proxyTargetClass) {

		String originalBeanName = definition.getBeanName();
		BeanDefinition targetDefinition = definition.getBeanDefinition();
        // **1**
		String targetBeanName = getTargetBeanName(originalBeanName);

		// Create a scoped proxy definition for the original bean name,
		// "hiding" the target bean in an internal target definition.
		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.
		}
		else {
			proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
		}

		// Copy autowire settings from original bean definition.
		proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
		proxyDefinition.setPrimary(targetDefinition.isPrimary());
		if (targetDefinition instanceof AbstractBeanDefinition) {
			proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
		}

		// The target bean should be ignored in favor of the scoped proxy.
		targetDefinition.setAutowireCandidate(false);
		targetDefinition.setPrimary(false);

		// Register the target bean as separate bean in the factory.
		registry.registerBeanDefinition(targetBeanName, targetDefinition);

		// Return the scoped proxy definition as primary bean definition
		// (potentially an inner bean).
		return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
	}

	public static String getTargetBeanName(String originalBeanName) {
		return TARGET_NAME_PREFIX + originalBeanName;
	}
	private static final String TARGET_NAME_PREFIX = "scopedTarget.";

该方法主要做了两件事:

1、创建一个代理Bean对象,单例的,bean对象名称为之前的名字,示例为:beanB。

2、将之前的bean对象名称在//**1**处改为:scopedTarget.beanB,并注册。

3、代理Bean对象的class为ScopedProxyFactoryBean。通过ScopedProxyFactoryBean创建cglib对象,并设置TargetSource为SimpleBeanTargetSource类。

ScopedProxyFactoryBean类:

public class ScopedProxyFactoryBean extends ProxyConfig
		implements FactoryBean<Object>, BeanFactoryAware, AopInfrastructureBean {

	/** The TargetSource that manages scoping. */
	private final SimpleBeanTargetSource scopedTargetSource = new SimpleBeanTargetSource();

	public void setTargetBeanName(String targetBeanName) {
		this.targetBeanName = targetBeanName;
		this.scopedTargetSource.setTargetBeanName(targetBeanName);
	}

	@Override
	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);
		pf.setTargetSource(this.scopedTargetSource);

		Assert.notNull(this.targetBeanName, "Property 'targetBeanName' is required");
		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.
		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.
		pf.addInterface(AopInfrastructureBean.class);

		this.proxy = pf.getProxy(cbf.getBeanClassLoader());
	}


	@Override
	public Object getObject() {
		if (this.proxy == null) {
			throw new FactoryBeanNotInitializedException();
		}
		return this.proxy;
	}
    ........
}

通过ScopedProxyFactoryBean创建cglib对象,targetSource是SimpleBeanTargetSource对象。

public class SimpleBeanTargetSource extends AbstractBeanFactoryBasedTargetSource {
	@Override
	public Object getTarget() throws Exception {
		return getBeanFactory().getBean(getTargetBeanName());
	}
}

该对象获取bean对象的时候,是从spring工厂中获取beanName为scopedTarget.beanB的对象。也就是创建一个单例的动态代理对象,再被aop拦截的时候,会通过SimpleBeanTargetSource获取源bean对象,实现beanB的每次创建。aop拦截方法在CglibAopProxy类的内部类DynamicAdvisedInterceptor的intercept方法

		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

通过target = targetSource.getTarget();获取源对象要执行的方法。也就是SimpleBeanTargetSource获取的BeanB对象。

三、@RefreshScope

@RefreshScope注解底层是@Scope

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope("refresh")
@Documented
public @interface RefreshScope {

	/**
	 * @see Scope#proxyMode()
	 * @return proxy mode
	 */
	ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

将Scope的value定义为了refresh,那么肯定就要用注册到scopes的地方。

@RefreshScope的注解是springboot的注解,在启动时会加载RefreshAutoConfiguration类。

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RefreshScope.class)
@ConditionalOnProperty(name = RefreshAutoConfiguration.REFRESH_SCOPE_ENABLED,
		matchIfMissing = true)
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
public class RefreshAutoConfiguration {

	/**
	 * Name of the refresh scope name.
	 */
	public static final String REFRESH_SCOPE_NAME = "refresh";

	/**
	 * Name of the prefix for refresh scope.
	 */
	public static final String REFRESH_SCOPE_PREFIX = "spring.cloud.refresh";

	/**
	 * Name of the enabled prefix for refresh scope.
	 */
	public static final String REFRESH_SCOPE_ENABLED = REFRESH_SCOPE_PREFIX + ".enabled";

	@Bean
	@ConditionalOnMissingBean(RefreshScope.class)
	public static RefreshScope refreshScope() {
		return new RefreshScope();
	}

	@Bean
	@ConditionalOnMissingBean
	public static LoggingRebinder loggingRebinder() {
		return new LoggingRebinder();
	}

	@Bean
	@ConditionalOnMissingBean
	public ContextRefresher contextRefresher(ConfigurableApplicationContext context,
			RefreshScope scope) {
		return new ContextRefresher(context, scope);
	}

RefreshScope对象

@ManagedResource
public class RefreshScope extends GenericScope implements ApplicationContextAware,
		ApplicationListener<ContextRefreshedEvent>, Ordered 

RefreshScope继承自GenericScope

public class GenericScope implements Scope, BeanFactoryPostProcessor,
		BeanDefinitionRegistryPostProcessor, DisposableBean {

	public static final String SCOPED_TARGET_PREFIX = "scopedTarget.";

	private static final Log logger = LogFactory.getLog(GenericScope.class);

	private BeanLifecycleWrapperCache cache = new BeanLifecycleWrapperCache(
			new StandardScopeCache());

	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
			throws BeansException {
		this.beanFactory = beanFactory;
		beanFactory.registerScope(this.name, this);
		setSerializationId(beanFactory);
	}
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
			throws BeansException {
		for (String name : registry.getBeanDefinitionNames()) {
			BeanDefinition definition = registry.getBeanDefinition(name);
			if (definition instanceof RootBeanDefinition) {
				RootBeanDefinition root = (RootBeanDefinition) definition;
				if (root.getDecoratedDefinition() != null && root.hasBeanClass()
						&& root.getBeanClass() == ScopedProxyFactoryBean.class) {
					if (getName().equals(root.getDecoratedDefinition().getBeanDefinition()
							.getScope())) {
						root.setBeanClass(LockedScopedProxyFactoryBean.class);
						root.getConstructorArgumentValues().addGenericArgumentValue(this);
						// surprising that a scoped proxy bean definition is not already
						// marked as synthetic?
						root.setSynthetic(true);
					}
				}
			}
		}
	}
}

1、postProcessBeanFactory方法将RefreshScope注册到beanFatory中。当AbstractBeanFactory.doGetBean执行时

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);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}

scopes.get("refresh"),就会调用GenericScope的get方法

	
   private BeanLifecycleWrapperCache cache = new BeanLifecycleWrapperCache(
			new StandardScopeCache());

   public Object get(String name, ObjectFactory<?> objectFactory) {
		BeanLifecycleWrapper value = this.cache.put(name,
				new BeanLifecycleWrapper(name, objectFactory));
		this.locks.putIfAbsent(name, new ReentrantReadWriteLock());
		try {
			return value.getBean();
		}
		catch (RuntimeException e) {
			this.errors.put(name, e);
			throw e;
		}
	}

  public class StandardScopeCache implements ScopeCache {

	private final ConcurrentMap<String, Object> cache = new ConcurrentHashMap<String, Object>();

	public Object remove(String name) {
		return this.cache.remove(name);
	}

	public Collection<Object> clear() {
		Collection<Object> values = new ArrayList<Object>(this.cache.values());
		this.cache.clear();
		return values;
	}

	public Object get(String name) {
		return this.cache.get(name);
	}

	public Object put(String name, Object value) {
		Object result = this.cache.putIfAbsent(name, value);
		if (result != null) {
			return result;
		}
		return value;
	}

}

该方法将beanName作为key,将beanName和objectFactory封装成BeanLifecycleWrapper作为value,放入到StandardScopeCache对象中,在StandardScopeCache对象中,由ConcurrentMap存储。

GenericScope的get方法返回是BeanLifecycleWrapper.getBean()方法

	private static class BeanLifecycleWrapper {
		public Object getBean() {
			if (this.bean == null) {
				synchronized (this.name) {
					if (this.bean == null) {
						this.bean = this.objectFactory.getObject();
					}
				}
			}
			return this.bean;
		}
    }

2、postProcessBeanDefinitionRegistry方法,将doScan中代理bean对象的class由ScopedProxyFactoryBean设置为LockedScopedProxyFactoryBean。LockedScopedProxyFactoryBean继承ScopedProxyFactoryBean。

	public static class LockedScopedProxyFactoryBean<S extends GenericScope>
			extends ScopedProxyFactoryBean implements MethodInterceptor {

		public Object invoke(MethodInvocation invocation) throws Throwable {
			Method method = invocation.getMethod();
			if (AopUtils.isEqualsMethod(method) || AopUtils.isToStringMethod(method)
					|| AopUtils.isHashCodeMethod(method)
					|| isScopedObjectGetTargetObject(method)) {
				return invocation.proceed();
			}
			Object proxy = getObject();
			ReadWriteLock readWriteLock = this.scope.getLock(this.targetBeanName);
			if (readWriteLock == null) {
				if (logger.isDebugEnabled()) {
					logger.debug("For bean with name [" + this.targetBeanName
							+ "] there is no read write lock. Will create a new one to avoid NPE");
				}
				readWriteLock = new ReentrantReadWriteLock();
			}
			Lock lock = readWriteLock.readLock();
			lock.lock();
			try {
				if (proxy instanceof Advised) {
					Advised advised = (Advised) proxy;
					ReflectionUtils.makeAccessible(method);
					return ReflectionUtils.invokeMethod(method,
							advised.getTargetSource().getTarget(),
							invocation.getArguments());
				}
				return invocation.proceed();
			}
			// see gh-349. Throw the original exception rather than the
			// UndeclaredThrowableException
			catch (UndeclaredThrowableException e) {
				throw e.getUndeclaredThrowable();
			}
			finally {
				lock.unlock();
			}
		}

在执行aop方法时,通过getObject()获取ScopedProxyFactoryBean创建的动态代理对象,在执行真正方法时advised.getTargetSource().getTarget(),传入的时每次创造的Bean对象。

三、总结

@Scope

1、@Scope代表spring Bean对象的作用域,一般分为singleton、prototype、request、session、application。其中request、session、application的缓存在GenericWebApplicationContext.postProcessBeanFactory方法中创建

2、@Scope的注解proxyMode的参数,默认为DEFAULT,还有INTERFACES、TARGET_CLASS两种。interfaces主要使用jdk的动态代理,target_class使用cglib代理。

3、@Scope("protype",proxyMode= TARGET_CLASS )创建动态代理时,会将注册到spring的bean对象变为两个。一个是代理Bean,实现类是ScopedProxyFactoryBean,通过SimpleBeanTargetSource获取名字scopedTarget.beanName的原Bean。另一个是将原bean名字改为scopedTarget.beanName,注册到spring中。

4、前台应用通过getBean("beanName")获取的是代理bean,真正执行方法时,由于aop的intercept方法会获取targetSource.getTarget(),也就是SimpleBeanTargetSource的getTarget()方法,该方法会调用spring,getBeanFactory().getBean(getTargetBeanName())返回每次新创建的原Bean。从而实现嵌套Bean的每次新建。

@RefreshScope

1、@RefreshScope注解底层是@Scope

2、postProcessBeanFactory方法将RefreshScope注册到beanFatory中,实现和request、session、application一样的缓存作用。

3、RefreshScope由RefreshAutoConfiguration类注入,get方法将beanName作为key,将beanName和objectFactory封装成BeanLifecycleWrapper作为value,放入到StandardScopeCache对象中,在StandardScopeCache对象中,由ConcurrentMap存储。

4、@RefreshScope和@Scope("prototype")区别在于

(1)作用域不同,@RefreshScope属于除singleton和prototype的扩展,而@Scope属于范围从四singleton、prototype、到其他扩展

(2)用法不同。@RefreshScope实现了接受通知后(如调用ContextRefresher.refresh方法,该方法会把StandardScopeCache的map清空)再新建Bean。而@Scope("protype")每次都会新创建。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值