Spring之AOP底层源码解读(更新中)

1. 什么是spring的Aop

        在进行源码解读之前,大家需要对Spring的Aop有基础的认识和理解,参考文章:Spring之AOP理解与应用-优快云博客

2. 源码解读

        接下来,我们对AOP的源码进行一个解读。

2.1 动态代理

        如果你已经对spring的Aop已经有了基础的认识,那么你一定知道它的底层是用动态代理实现的。作为一个java程序员,我们都知道,实现动态代理的方式有两种,一种是jdk自生提供了一种创建代理对象的动态代理机制,其特点是代理类必须实现了接口;另一种是cglib技术。那么Spring中到底用了哪一种呢?

        其实spring中这两种代理技术都用到了,它把这两种动态代理的方式进行了封装,封装成的类叫做ProxyFactory,表示是创建代理对象的一个工厂。通过ProxyFactory,我们可以不用关心到底是用cglib还是jdk动态代理了,ProxyFactory会帮我们去判断,如果要代理的类实现了接口,那么ProxyFactory底层就会用jdk动态代理,如果没有实现接口,就会用cglib技术。

        以下源码则是spring在生成AOP代理对象之前需要决定到底是使用JDK动态代理还是CGLIB技术:

AopProxyFactory的子类DefaultAopProxyFactory中的createAopProxy方法
@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		// 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快
		// 或者isProxyTargetClass为true,
		// 或者被代理对象没有实现接口,
		// 或者只实现了SpringProxy这个接口
		// 那么则利用Cglib进行动态代理,但如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理

		// 其他情况都会进行JDK动态代理,比如被代理类实现了除SpringProxy接口之外的其他接口

		// 是不是在GraalVM虚拟机上运行
		if (!NativeDetector.inNativeImage() &&
				(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.");
			}
			// targetClass是接口,直接使用Jdk动态代理
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			// 使用Cglib
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			// 使用Jdk动态代理
			return new JdkDynamicAopProxy(config);
		}
	}

2.2 代理对象创建过程

        根据上述源码中,我们得知,spring会自己判断用JDK动态代理还是Cglib动态代理,接下来,我们看一下,spring如何创建一个动态代理的对象;

2.2.1 Spring中JDK动态代理创建代理对象

spring使用JDK代理创建代理对象的整体脉络

1. 在构造JdkDynamicAopProxy对象时,会先拿到被代理对象自己所实现的接口,并且额外的增加SpringProxy、Advised、DecoratingProxy三个接口,组合成一个Class[],并赋值给
proxiedInterfaces属性。
2. 并且检查这些接口中是否定义了equals()、hashcode()方法。
3. 执行 Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this) ,得到代理对象,JdkDynamicAopProxy作为InvocationHandler,代理对象在执行某个方法时,会进入到
JdkDynamicAopProxy的**invoke()**方法中

源码分析: 

spring JDK动态代理的类是:JdkDynamicAopProxy,下述源码是JdkDynamicAopProxy的构造函数:

/**
	 * Construct a new JdkDynamicAopProxy for the given AOP configuration.
	 * @param config the AOP configuration as AdvisedSupport object
	 * @throws AopConfigException if the config is invalid. We try to throw an informative
	 * exception in this case, rather than let a mysterious failure happen later.
	 */
	public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		// 设置JDK动态代理所要代理的接口
		this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		//判断被代理的接口中是否定义了equals()、hashCode()方法,如果程序员在接口中手动定义了这两个方法,则也会进行代理
		findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
	}

接下来,我们看一下如何设置proxiedInterfaces属性的方法:AopProxyUtils中的static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) 

/**
	 * Determine the complete set of interfaces to proxy for the given AOP configuration.
	 * <p>This will always add the {@link Advised} interface unless the AdvisedSupport's
	 * {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the
	 * {@link org.springframework.aop.SpringProxy} marker interface.
	 * @param advised the proxy config
	 * @param decoratingProxy whether to expose the {@link DecoratingProxy} interface
	 * @return the complete set of interfaces to proxy
	 * @since 4.3
	 * @see SpringProxy
	 * @see Advised
	 * @see DecoratingProxy
	 */
	static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
		// 被代理对象自己所实现的接口
		Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();

		// 如果被代理对象没有实现接口,则判断被代理类是不是接口,或者被代理类是不是已经经过JDK动态代理之后的类从而获取想对应的接口
		if (specifiedInterfaces.length == 0) {
			// No user-specified interfaces: check whether target class is an interface.
			Class<?> targetClass = advised.getTargetClass();
			if (targetClass != null) {
				if (targetClass.isInterface()) {
					advised.setInterfaces(targetClass);
				}
				else if (Proxy.isProxyClass(targetClass)) {
					advised.setInterfaces(targetClass.getInterfaces());
				}
				specifiedInterfaces = advised.getProxiedInterfaces();
			}
		}

		// 添加三个Spring内置接口:SpringProxy、Advised、DecoratingProxy
		List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3);
		for (Class<?> ifc : specifiedInterfaces) {
			// Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17)
			if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) {
				proxiedInterfaces.add(ifc);
			}
		}
		if (!advised.isInterfaceProxied(SpringProxy.class)) {
			proxiedInterfaces.add(SpringProxy.class);
		}
		if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) {
			proxiedInterfaces.add(Advised.class);
		}
		if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) {
			proxiedInterfaces.add(DecoratingProxy.class);
		}
		return ClassUtils.toClassArray(proxiedInterfaces);
	}

紧接着我们看一下检查equals()和hashcode()的方法

	/**
	 * Finds any {@link #equals} or {@link #hashCode} method that may be defined
	 * on the supplied set of interfaces.
	 * @param proxiedInterfaces the interfaces to introspect
	 */
	private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
		// 判断被代理的接口中是否定义了equals()、hashCode()方法,如果程序员在接口中手动定义了这两个方法,则也会进行代理
		// 否则这两个方法是不会走代理逻辑的
		for (Class<?> proxiedInterface : proxiedInterfaces) {
			Method[] methods = proxiedInterface.getDeclaredMethods();
			for (Method method : methods) {
				if (AopUtils.isEqualsMethod(method)) {
					this.equalsDefined = true;
				}
				if (AopUtils.isHashCodeMethod(method)) {
					this.hashCodeDefined = true;
				}
				if (this.equalsDefined && this.hashCodeDefined) {
					return;
				}
			}
		}
	}

接下来,我们看一下如何得到一个JDK的动态代替对象;也就是JdkDynamicAopProxy的getProxy()这个方法;

@Override
	public Object getProxy() {
		return getProxy(ClassUtils.getDefaultClassLoader());
	}

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		// 得到代理对象作为InvocationHandler,
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}

最后,我们看一下  代理对象执行某个方法时,会进入到JdkDynamicAopProxy的invoke()方法中,这个方法的具体实现

/**
	 * Implementation of {@code InvocationHandler.invoke}.
	 * <p>Callers will see exactly the exception thrown by the target,
	 * unless a hook method throws an exception.
	 */
	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		// 拿到被代理对象
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			// 如果接口中没有定义equals()方法,那么则直接调用,不走代理
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				// 得到代理对象的类型,而不是所实现的接口
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				// 也是直接调用Advised接口中的方法,不走代理逻辑
				// 其实就是利用代理对象获取ProxyFactory中的信息
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去
			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);

			// Get the interception chain for this method.
			// 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// Check whether we have any advice. If we don't, we can fallback on direct
			// reflective invocation of the target, and avoid creating a MethodInvocation.
			if (chain.isEmpty()) {
				// 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.
				// 如果没有Advice,则直接调用对应方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

2.2.2 Spring中Cglib动态代理创建代理对象

Spring中Cglib动态代理创建代理对象整体脉络:

1. 创建Enhancer对象。
2. 设置Enhancer的superClass为通过ProxyFactory.setTarget()所设置的对象的类。
3. 设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及
SpringProxy、Advised、DecoratingProxy接口。
4. 设置Enhancer的Callbacks为DynamicAdvisedInterceptor。
5. 最后创建一个代理对象,代理对象在执行某个方法时,会进入DynamicAdvisedInterceptor的intercept()方法中。

源码解读: 

在spring中,得到一个Cglib动态代理创建的代理对象,主要通过ObjenesisCglibAopProxy
类的getProxy()方法,其具体实现在其父类CglibAopProxy中,我们看一下这个方法源码的解读:

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			// 被代理的类
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			// 如果被代理类本身就已经是Cglib所生成的代理类了
			if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
				// 获取真正的被代理类
				proxySuperClass = rootClass.getSuperclass();
				// 获取被代理类所实现的接口
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...  创建Enhancer对象
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}

			// 被代理类,代理类的父类   设置Enhancer的superClass为通过ProxyFactory.setTarget()所设置的对象的类
			enhancer.setSuperclass(proxySuperClass);
			// 代理类额外要实现的接口   设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及
			//SpringProxy、Advised、DecoratingProxy接口
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

			// 获取和被代理类所匹配的Advisor   设置Enhancer的Callbacks为DynamicAdvisedInterceptor
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

接下来我们看一下  如何设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advised、DecoratingProxy接口。 这个方法为AopProxyUtils类中的static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) 方法,具体源码解析如下:

	/**
	 * Determine the complete set of interfaces to proxy for the given AOP configuration.
	 * <p>This will always add the {@link Advised} interface unless the AdvisedSupport's
	 * {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the
	 * {@link org.springframework.aop.SpringProxy} marker interface.
	 * @param advised the proxy config
	 * @param decoratingProxy whether to expose the {@link DecoratingProxy} interface
	 * @return the complete set of interfaces to proxy
	 * @since 4.3
	 * @see SpringProxy
	 * @see Advised
	 * @see DecoratingProxy
	 */
	static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
		// 被代理对象自己所实现的接口
		Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();

		// 如果被代理对象没有实现接口,则判断被代理类是不是接口,或者被代理类是不是已经经过JDK动态代理之后的类从而获取想对应的接口
		if (specifiedInterfaces.length == 0) {
			// No user-specified interfaces: check whether target class is an interface.
			Class<?> targetClass = advised.getTargetClass();
			if (targetClass != null) {
				if (targetClass.isInterface()) {
					advised.setInterfaces(targetClass);
				}
				else if (Proxy.isProxyClass(targetClass)) {
					advised.setInterfaces(targetClass.getInterfaces());
				}
				specifiedInterfaces = advised.getProxiedInterfaces();
			}
		}

		// 添加三个Spring内置接口:SpringProxy、Advised、DecoratingProxy
		List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3);
		for (Class<?> ifc : specifiedInterfaces) {
			// Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17)
			if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) {
				proxiedInterfaces.add(ifc);
			}
		}
		if (!advised.isInterfaceProxied(SpringProxy.class)) {
			proxiedInterfaces.add(SpringProxy.class);
		}
		if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) {
			proxiedInterfaces.add(Advised.class);
		}
		if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) {
			proxiedInterfaces.add(DecoratingProxy.class);
		}
		return ClassUtils.toClassArray(proxiedInterfaces);
	}

我们再看一下如何设置Enhancer的Callbacks为DynamicAdvisedInterceptor。还是在CglibAopProxy这个类中

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// Choose an "aop" interceptor (used for AOP calls).
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// Choose a "straight to target" interceptor. (used for calls that are
		// unadvised but can return this). May be required to expose the proxy.
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
		}
		else {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
		}

		// Choose a "direct to target" dispatcher (used for
		// unadvised calls to static targets that cannot return this).
		Callback targetDispatcher = (isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

		Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,  // for normal advice,执行Interceptor链
				targetInterceptor,  // invoke target without considering advice, if optimized 将代理对象设置到ThreadLocal中,AopContext.setCurrentProxy(proxy)
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// If the target is a static one and the advice chain is frozen,
		// then we can make some optimizations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
				Method method = methods[x];
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
				this.fixedInterceptorMap.put(method, x);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
			this.fixedInterceptorOffset = mainCallbacks.length;
		}
		else {
			callbacks = mainCallbacks;
		}
		return callbacks;
	}

2.3 代理对象执行过程 

2.4 注解对应的MethodInterceptor

### Spring框架底层源码分析与解读 #### 1. Spring框架概述 Spring是一个轻量级的Java开发框架,旨在简化企业应用开发过程。它通过提供一系列模块化组件来支持应用程序的不同方面,例如依赖注入(DI)、面向切面编程(AOP)、声明式事务管理等[^3]。 #### 2. Spring的核心机制 Spring的核心机制主要围绕IoC(控制反转)和DI(依赖注入)。这些概念使得开发者可以更轻松地管理和配置对象之间的关系。具体而言: - **IoC容器**:负责创建、装配和管理Bean实例。其内部工作流程包括加载配置文件、注册Bean定义以及初始化Bean工厂等操作[^4]。 - **依赖注入**:允许将外部资源或服务引入到类中而无需显式编码连接逻辑。这通常通过构造器注入或者Setter方法完成,并可通过`@Autowired`注解进一步增强灵活性[^5]。 #### 3. 底层源码剖析 当启动基于Spring的应用程序时,整个生命周期涉及多个重要阶段,下面详细介绍几个关键部分: ##### (a) ApplicationContext 初始化 在典型的Spring项目,我们经常看到如下代码片段用于获取上下文环境: ```java ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ``` 这段简单的语句背后隐藏着复杂的初始化流程。实际上,在调用此构造函数之后紧接着执行的是 `refresh()` 方法,该方法包含了大量子步骤用来确保所有的Beans都被正确加载并准备好供后续使用[^4]。 以下是其中一些显著的操作环节及其顺序描述: 1. **准备环境设置** - 设置当前线程ClassLoader以便于反射查找Class信息。 2. **读取配置元数据** - 解析XML或其他形式的配置文件内容转换成内存中的结构表示形式(即BeanDefinition)。 3. **提前实例化单例beans** - 对标记为lazy-init=false 的那些bean 进行预处理从而加快第一次访问速度减少延迟时间成本。 ... 由于篇幅原因无法逐一列举全部细节,请参照实际调试过程中观察到的现象作为补充参考资料。 ##### (b) BeanFactory 和 FactoryBean的区别 虽然两者名字相似但用途完全不同。“BeanFactory” 是一个接口代表基本级别的 IoC 容器功能;而 “FactoryBean” 则是用来生产特定类型的 bean 实例的一种特殊模式实现方式之一。 #### 4. 总结 通过对上述要点的学习可以看出,Spring 不仅提供了强大的抽象能力帮助程序员构建复杂的企业解决方案,而且它的设计哲学也值得深入探讨学习借鉴. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑜伽娃娃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值