Spring源码之AOP(四)——ScopedProxy

          我们看一段代码,先定义一个多例的Bean:

@Component
@Scope(value = DefaultListableBeanFactory.SCOPE_PROTOTYPE)
public class ScopedProxyBean {

    public void code() {
        System.out.println(this.hashCode());
    }
}

        再定义一个单例Bean,通过@Autowired注解把上面的多例Bean注入进去,打印hashCode:

@Component
public class SingleBean {

    @Autowired
    private ScopedProxyBean scopedProxyBean;

    public void test() {
        scopedProxyBean.code();
    }
}

        单元测试: 

    @Test
    public void testScopedProxy() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);
        SingleBean bean = applicationContext.getBean(SingleBean.class);
        for (int i = 0; i < 10; i++) {
            bean.test();
        }
    }

        不是多例的吗,为什么hashCode 却是一样的? 

        因为SingleBean是单例,在属性赋值的时候,@Autowired注解的是引用类,会触发ScopedProxyBean的getBean()操作,拿到实例对象,然后进行反射调用,但只会拿到一个(在启动的时候),即使ScopedProxyBean是多例,但也只会创建一次,因为在Spring的启动,SingleBean的实例化过程中就定了,所以,即使调用多次,但实例确实同一个,所以打印结果一致也就不奇怪了。

        对上面的代码做一点改动,在注解上加代理模式的配置:

        proxyMode = ScopedProxyMode.TARGET_CLASS
@Component
@Scope(value = DefaultListableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ScopedProxyBean {

    public void code() {
        System.out.println(this.hashCode());
    }
}

        再看打印结果:

        此时却时不一样的,这又是为什么?

        看一下ScopedProxyMode.TARGET_CLASS:

​
public enum ScopedProxyMode {

	/**
	 * Default typically equals {@link #NO}, unless a different default
	 * has been configured at the component-scan instruction level.
	 */
	DEFAULT,

	/**
	 * Do not create a scoped proxy.
	 * <p>This proxy-mode is not typically useful when used with a
	 * non-singleton scoped instance, which should favor the use of the
	 * {@link #INTERFACES} or {@link #TARGET_CLASS} proxy-modes instead if it
	 * is to be used as a dependency.
	 */
	NO,

	/**
	 * Create a JDK dynamic proxy implementing <i>all</i> interfaces exposed by
	 * the class of the target object.
	 */
	INTERFACES,

	/**
	 * Create a class-based proxy (uses CGLIB).采用的是CGLIB的代理
	 */
	TARGET_CLASS

}

​

        采用的是CGLIB代理,之前我们实例化的是原始对象,之后加了这个,依赖注入的是代理对象,如果代理对象去调用目标方法,就会走切面,切面中拿到目标实例再进行方法调用,在拿BeanDefinition的时,发现它是多例的,每次getBean()拿到的实例都是新创建的,所以hashCode不一样。

        但是,为什么这里依赖注入的是代理对象?

        通过前面系列的源码,我们看扫描注解及Scope的填充过程,就是这个解析配置信息的类ConfigurationClassPostProcessor:

        ConfigurationClassPostProcessor.processConfigBeanDefinitions()——>

        解析过程ConfigurationClassParser#parse()——>

        ConfigurationClassParser#processConfigurationClass——>

        ConfigurationClassParser#doProcessConfigurationClass——>

        ComponentScanAnnotationParser#parse——>

        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) {
			// 根据扫描路径,得到BeanDefinition
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			// 解析class
			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) {
					// 解析@lazy、@Primary、@DependsOn、@Role、@Description
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				// 检查Spring容器是否已经存在beanName
				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;
	}

​

        Scope是this.scopeMetadataResolver.resolveScopeMetadata(candidate);

        所属类:org.springframework.context.annotation.AnnotationScopeMetadataResolver

	@Override
	public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
		ScopeMetadata metadata = new ScopeMetadata();
		if (definition instanceof AnnotatedBeanDefinition) {
			AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
			// this.scopeAnnotationType就是@Scope注解
			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
					annDef.getMetadata(), this.scopeAnnotationType);
			if (attributes != null) {
				metadata.setScopeName(attributes.getString("value"));
				// 根据注解中proxyMode的拿到代理模式
				ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
				if (proxyMode == ScopedProxyMode.DEFAULT) {
					proxyMode = this.defaultProxyMode;
				}
				metadata.setScopedProxyMode(proxyMode);
			}
		}
		return metadata;
	}

        根据注解中proxyMode的拿到代理模式,ScopedProxyMode.DEFAULT为默认的代理模式,表示没有。

         获取代理模式就是这里,参数中的BeanDefinition是通过填充传进来的:

​
definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

        所属类:org.springframework.context.annotation.AnnotationConfigUtils

	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);
		// 如果代理模式是TARGET_CLASS,就创建代理
		return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
	}

         所属类:org.springframework.context.annotation.ScopedProxyCreator

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

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

        创建代理就是创建一个新的BeanDefinition:

        所属类:org.springframework.aop.scope.ScopedProxyUtils

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

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

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

		// Copy autowire settings from original bean definition.
		// 代理实例的配置从原始的BeanDefnition复制autowire配置(没有配置默认为true)
		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.
		// 目标对象autowire属性设置为false,表示容器在查找自动装配对象时,不考虑该Bean
		targetDefinition.setAutowireCandidate(false);
		// 将之前的BeanDefinition覆盖
		targetDefinition.setPrimary(false);

		// Register the target bean as separate bean in the factory.
		// 将新的targetDefinition注册进去
		registry.registerBeanDefinition(targetBeanName, targetDefinition);

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

        我们看一下这个ScopedProxyFactoryBean:

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

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

	/** The name of the target bean. */
	@Nullable
	private String targetBeanName;

	/** The cached singleton proxy. */
	@Nullable
	private Object proxy;


	/**
	 * Create a new ScopedProxyFactoryBean instance.
	 */
	public ScopedProxyFactoryBean() {
		setProxyTargetClass(true);
	}


	/**
	 * Set the name of the bean that is to be scoped.
	 */
	public void setTargetBeanName(String targetBeanName) {
		this.targetBeanName = targetBeanName;
		this.scopedTargetSource.setTargetBeanName(targetBeanName);
	}

	// 先执行(这是BeanFactoryAware的方法)
	@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);
		// 后面代理对象getTargetSource时会调用到TargetSource的getTarget()方法
		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());
		// 设置代理工厂,代理对象调用的时候,就会执行DelegatingIntroductionInterceptor的invoke()方法
		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);
		// 返回代理对象(CGLIB代理)
		this.proxy = pf.getProxy(cbf.getBeanClassLoader());
	}

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

	@Override
	public Class<?> getObjectType() {
		if (this.proxy != null) {
			return this.proxy.getClass();
		}
		// 该类实例化时就会调用上面的getObject()方法
		return this.scopedTargetSource.getTargetClass();
	}

         将CGLIB产生的代理对象返回,CGLIB的代理逻辑会进入到DynamicAdvisedInterceptor类,它是CglibAopProxy的内部类,执行intercept()方法:

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
 
		private final AdvisedSupport advised;
 
		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}
 
		@Override
		@Nullable
		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);

      ----省略无关代码----

        target = targetSource.getTarget()就会调到SimpleBeanTargetSource.getTarget(),把代理对象(实例代码中的ScopedProxyBean)返回:

public class SimpleBeanTargetSource extends AbstractBeanFactoryBasedTargetSource {

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

         依赖注入的才是代理对象,代理对象走切面才会调用TargetSource.getTarget()方法,getTarget()中才会执行getBean(),每次会生成新的实例。 

         ScopedProxyFactoryBean实现了FactoryBean接口,在这里会生成代理,getObjectType()方法就是在依赖注入时执行,走切面的逻辑this.scopedTargetSource.getTargetClass()返回的就是代理实例,getObjectType()返回的是依赖注入对象,上面示例代码中ScopedProxyBean的依赖注入最终会执行ScopedProxyFactoryBean.getObject()方法:

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

猜你喜欢

转载自blog.csdn.net/qq_40213907/article/details/121180619