Spring基于注解开发的注解使用之AOP(部分源代码分析)

AOP底层实现动态代理

1、导入spring-aop包依赖

<!--aopV1-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
	<scope>test</scope>
</dependency>
<!--aopV2-->
<dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjweaver</artifactId>
</dependency>

2、在配置类加入注解

@EnableAspectJAutoProxy//启用AOP切面(开启注解版的AOP功能)

3、@Aspect

在切面类上加入@Aspect表示这是一个切面

4、切面配置

spring官方文档(https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-introduction-defn)

  1.  /*

  2. 标识这个方法是个前置通知, 切点表达式表示执行任意类的任意方法.

  3. 第一个 * 代表匹配任意修饰符及任意返回值,

  4. 第二个 * 代表任意类的对象,

  5. 第三个 * 代表任意方法,

  6. 参数列表中的 .. 匹配任意数量的参数

  7. */

  • The execution of any public method:

        execution(public * *(..))
  • The execution of any method with a name that begins with set:

        execution(* set*(..))
  • The execution of any method defined by the AccountService interface:

        execution(* com.xyz.service.AccountService.*(..))
  • The execution of any method defined in the service package:

        execution(* com.xyz.service.*.*(..))
  • The execution of any method defined in the service package or one of its sub-packages:

        execution(* com.xyz.service..*.*(..))
  • Any join point (method execution only in Spring AOP) within the service package:

        within(com.xyz.service.*)
  • Any join point (method execution only in Spring AOP) within the service package or one of its sub-packages:

        within(com.xyz.service..*)
  • Any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface:

        this(com.xyz.service.AccountService)

@Before("execution(* com.xyz.myapp.dao.*.*(..))")

@AfterReturning("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")

指定返回参数

@AfterReturning(
        pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()",
        returning="retVal")
public void doAccessCheck(Object retVal) {
        // ...
}

制定异常(返回)

@Aspect
public class AfterThrowingExample {

    @AfterThrowing(
        pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()",
        throwing="ex")
    public void doRecoveryActions(DataAccessException ex) {
        // ...
    }
}

获取输出参数

//先定义切点(Pointcut)
@Pointcut("com.xyz.myapp.CommonPointcuts.dataAccessOperation() && args(account,..)")
private void accountDataAccessOperation(Account account) {}

//使用切点
@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account) {
    // ...
}

 

使用

@Configuration
@ComponentScan("com.test2")
@EnableAspectJAutoProxy
public class Config1 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext content = new AnnotationConfigApplicationContext(Config1.class);
        System.out.println("********BeanDefinition*********");
        Arrays.stream(content.getBeanDefinitionNames()).forEach(val -> {
            System.out.println(val);
        });
        System.out.println("********BeanDefinition*********");
        System.out.println("############spring--容器启动完成############");
        TestService testService = content.getBean(TestService.class);
        testService.addUser();
    }

}

//控制台输出
LogAspect--around-before
LogAspect--before
com.test2.bean.TestService执行addUser动作
LogAspect--afterReturning返回结果:添加成功
LogAspect--after
LogAspect--around-after返回值:添加成功

Aspect类定义

package com.test2.bean;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * Created by user on 2021/1/18.
 */
@Component
@Aspect
public class LogAspect {

    @Pointcut("execution(* com.test2.bean.TestService.*(..))")
    public void pointCut() {
    }
    
    //JoinPoint必须是方法的第一个参数,否则spring会无法识别。具体查看spring源码分析
    @Before("execution(public String com.test2.bean.TestService.addUser())")
    public void before(JoinPoint point) {
        System.out.println(point.getSignature().getName());//方法
        System.out.println(point.getArgs());//参数
        System.out.println("LogAspect--before");
    }

    @After(value = "pointCut()")
    public void after() {
        System.out.println("LogAspect--after");
    }

    @AfterReturning(value = "pointCut()", returning = "result")
    public void afterReturning(Object result) {
        System.out.println("LogAspect--afterReturning" + "返回结果:" + result);
    }

    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void afterThrowing(Exception exception) {
        System.out.println("LogAspect--AfterThrowing" + exception.getMessage());
    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("LogAspect--around-before");
        long beginTime = System.currentTimeMillis();
        Object result = point.proceed();//实际方法执行
        long time = System.currentTimeMillis() - beginTime;
        System.out.println("LogAspect--around-after" + "返回值:" + result);
        return result;
    }
}
@Service
public class TestService {

    public String addUser() {
        System.out.println(this.getClass().getName() + "执行addUser动作");
        int i  = 1/0;//手动抛出异常【如果手动抛出异常时,afterThrowing会被执行,且能够接受到具体的异常信息】
        return "添加成功";
    }
}

AOP原理


@EnableAspectJAutoProxy

//加入AOP后,才开始起作用

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//给容器导入某个Bean
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}

导入组件(AspectJAutoProxyRegistrar)

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

}

给Spring容器导入Bean---AspectJAutoProxyRegistrar,由于实现了ImportBeanDefinitionRegistrar,也就是在Spring容器启动的时候会调用registerBeanDefinitions方法;

这个是invokeBeanFactoryPostProcessors的时候执行,这个可以给Spring容器直接导入Bean的定义;然后spring在IOC的时候,就会创建对应的bean

 

ImportBeanDefinitionRegistrar

 

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

关键方法执行

 

 

 

#Spring-AOP之AspectJ切面理解
+ 在配置类中加入@EnableAspectJAutoProxy注解支持
    (1)问题,为什么加入了@EnableAspectJAutoProxy注解后,spring-AOP就起作用了?
        (1)通过使用注解后,注解内部导入了org.springframework.context.annotation.AspectJAutoProxyRegistrar类【这个类起关键作用】
+ 注解@EnableAspectJAutoProxy定义
//org.springframework.context.annotation.AspectJAutoProxyRegistrar
@Import(AspectJAutoProxyRegistrar.class)//导入了AspectJAutoProxyRegistrar
public @interface EnableAspectJAutoProxy {}
+ AspectJAutoProxyRegistrar类干了什么事情?【@Import(AspectJAutoProxyRegistrar.class)//导入了AspectJAutoProxyRegistrar】
AspectJAutoProxyRegistrar类实现了接口 ImportBeanDefinitionRegistrar(org.springframework.context.annotation包)
  + 在spring容器初始化(refresh())的时候,会调用invokeBeanFactoryPostProcessors(beanFactory)方法
    //Invoke factory processors registered as beans in the context【执行工厂后置处理器,注册一个bean在spring-上下文】
    invokeBeanFactoryPostProcessors(beanFactory)
    在这个方法里面就实现了对实现接口ImportBeanDefinitionRegistrar的处理【具体可以看另一篇文章针对ImportBeanDefinitionRegistrar合适处理的分析】
    文章地址:https://blog.csdn.net/qqzhengwei/article/details/113102969
  + 上面执行完毕后,就会把 AspectJAutoProxyRegistrar 【完成AnnotationAwareAspectJAutoProxyCreator初始化new】
    org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator的registerBeanDefinitions方法
    + AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)//完成下面说的注册到spring容器中
    beanName=org.springframework.aop.config.internalAutoProxyCreator 实例为 AnnotationAwareAspectJAutoProxyCreator,注册到spring-beanFactory中
  + 最终给spring容器注册了beanName=org.springframework.aop.config.internalAutoProxyCreator,实例为 AnnotationAwareAspectJAutoProxyCreator
  + 上面只是把AnnotationAwareAspectJAutoProxyCreator的beanDefinition注册到spring容器,但是这个时候bean还没有被实例化
  + AnnotationAwareAspectJAutoProxyCreator 在何时被初始化的呢?
    【查看 AnnotationAwareAspectJAutoProxyCreator 类图结构】--看看他实现了什么接口,以及什么时候完成的初始化
        1)、实现了 BeanFactoryAware 接口,也就是在 AnnotationAwareAspectJAutoProxyCreator spring创建这个bean的时候,会注册 beanFactory实例进来
            这个时候就可以通过beanFactory放注册的bean
        2)、实现了 BeanPostProcessor ,bean的后置处理器【这个都是在bean实例化的时候做的动作】
            --postProcessBeforeInitialization 在bean初始化之前做的事情
            --postProcessAfterInitialization  在bean实例化之后做的事情
    + org.springframework.context.support.AbstractApplicationContext的refresh()
    + registerBeanPostProcessors(beanFactory);//(注册bean的后置处理器,用来拦截bean的创建)Register bean processors that intercept bean creation.
        + PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this)
            通过PostProcessorRegistrationDelegate去处理
            //通过beanFactory在spring容器中把上面定义的AnnotationAwareAspectJAutoProxyCreator给找到
            String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
            //通过beanFactory-根据beanName名称(org.springframework.aop.config.internalAutoProxyCreator)去容器中获取这个bean
            //getBean,去spring容器获取bean,如果spring容器找不到,就去创建;(bean的实例化过程实现)
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class)
            + getBean的执行链路
                org.springframework.beans.factory.support.AbstractBeanFactory类中的方法(为beanFactory的抽象类)
                1)、getBean(String name, Class<T> requiredType)
                2)、doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
                3)、getSingleton(String beanName, ObjectFactory<?> singletonFactory)最终还是会执行下面createBean方法
                3)、sharedInstance = getSingleton(beanName, () -> {return createBean(beanName, mbd, args))};之说核心方法
                4)、createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                --org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
                【这里执行了BeforeInstantiation】Object bean = resolveBeforeInstantiation(beanName, mbdToUse)
                //Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                5)、doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                   一、循环依赖问题解决(较早暴露bean)
                   二、createBeanInstance 通过无参构造函数实例化bean
                   三、populateBean 给bean的各种属性赋值
                   四、initializeBean 初始化bean
                      1)、invokeAwareMethods 调用实现了Aware接口的方法
                      2)、applyBeanPostProcessorsBeforeInitialization 执行前置处理器 postProcessBeforeInitialization
                      3)、invokeInitMethods 调用初始化方法:例如afterPropertiesSet实现InitializingBean接口
                      4)、postProcessAfterInitialization  执行后置处理器 postProcessAfterInitialization
                        【这个后置处理器就会调用 AnnotationAwareAspectJAutoProxyCreator 的postProcessBeforeInitialization和postProcessAfterInitialization方法】
    + 以上就完成了AnnotationAwareAspectJAutoProxyCreator的创建和注册到spring容器

AnnotationAwareAspectJAutoProxyCreator实现了接口BeanPostProcessor后置处理器,也就是以后创建任何Bean的都是都会调用

----》postProcessBeforeInitialization 

---》postProcessAfterInitialization

方法,这样就实现了拦截处理。


InstantiationAwareBeanPostProcessor 后置处理器作用(使用契机)


==================================【以下是在实例化之前做的事情】 doCreateBean之前做的
    + interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor
       InstantiationAwareBeanPostProcessor 也是一个BeanPostProcessor,只是是BeanPostProcessor的子接口
    + AnnotationAwareAspectJAutoProxyCreator ==> InstantiationAwareBeanPostProcessor【这个叫实例化之前的后置处理器】 
=========    
+ org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(beanFactory) 
   在spring容器初始化完成finishBeanFactoryInitialization
   【AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前都会有一个拦截的作用 因为他是一个 InstantiationAwareBeanPostProcessor 后置处理器】
   【在容器AbstractApplicationContext.finishBeanFactoryInitialization(beanFactory)执行时产生的效果】--实例化bean容器里面所有的bean
   + 遍历容器中所有的bean,依次创建getBean(beanName)对象;beanFactory的beanDefinitionNames属性
     + [+ getBean的执行链路]查看上面的getBean执行链路
     + 创建bean实例
        1)、先从缓存中看看是否存在bean实例;
            如果能够获取到直接从缓存中获取(单例的bean),如果不存在的话,否则创建bean;
        2)、createBean创建bean
            【BeanPostProcessors 是在对象创建完成,初始化前后调用】
            【InstantiationAwareBeanPostProcessor 是在对象,创建之前调用】
            1)、Object bean = resolveBeforeInstantiation(beanName, mbdToUse)执行:创建bean前的,处理器
                代码注释Give BeanPostProcessors a chance to return a proxy instead of the target bean instance
                给BeanPostProcessors(后置处理器)一个机会,来返回一个代理对象,来替代真实的对象【代理就是在这里开始的】
                + 【这里执行了BeforeInstantiation】Object bean = resolveBeforeInstantiation(beanName, mbdToUse)
                    + resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)
                        //执行前置
                        bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                            如果bp instanceof InstantiationAwareBeanPostProcessor 就执行后置处理器的postProcessBeforeInstantiation方法
                        if (bean != null) {
                            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                                执行后置--postProcessAfterInitialization
                        }
            2)、 希望后置处理器在这里可以返回一个代理对象,如果能返回就使用代理对象bean,如果不能返回,就在创建bean;
               Object beanInstance = doCreateBean(beanName, mbdToUse, args)     
+ AnnotationAwareAspectJAutoProxyCreator.postProcessBeforeInstantiation方法又干了什么事情呢?
   要获取代理bean这样获取
   BeanFactory接口里面的常量String FACTORY_BEAN_PREFIX = "&";
   BeanFactory.FACTORY_BEAN_PREFIX + beanName
   1)、postProcessBeforeInstantiation
      1)、判断当前bean是否已经增强
      2)、在判断beanClass是否是基础类型的(Advice、Pointcut、Advisor、AopInfrastructureBean、@AspectJ)
      3)、是否需要跳过shouldSkip()
         1)、获取候选的增强器(切面里面的通知方法)【List<Advisor> candidateAdvisors增强器集合】
          protected boolean shouldSkip(Class<?> beanClass, String beanName) {
             List<Advisor> candidateAdvisors = findCandidateAdvisors();
             for (Advisor advisor : candidateAdvisors) {
               if (advisor instanceof AspectJPointcutAdvisor &&
                      ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
                  return true;
                }
             }
            return super.shouldSkip(beanClass, beanName);
        }
         每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor;
         判断每一个增强器是否是 AspectJPointcutAdvisor 类型的;返回true
      2)、永远返回false
   2)、创建对象 postProcessAfterInitialization
        return wrapIfNecessary(bean, beanName, cacheKey);  //包装如果需要的情况下
        1)、获取当前bean的所有增强器(通知方法)  Object[]  specificInterceptors
            1、找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)
            2、获取到能在bean使用的增强器。
            3、给增强器排序使用@Order(3)数值越小,优先级越高。越优先执行
            2)、保存当前bean在advisedBeans中;
            3)、如果当前bean需要增强,创建当前bean的代理对象;
                1)、获取所有增强器(通知方法)
                2)、保存到proxyFactory
                3)、创建代理对象:Spring自动决定
                    JdkDynamicAopProxy(config);jdk动态代理;
                    ObjenesisCglibAopProxy(config);cglib的动态代理;
            4)、给容器中返回当前组件使用cglib增强了的代理对象;
            5)、以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;
   3)、目标方法执行   ;
        容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx);
        1)、CglibAopProxy.intercept();拦截目标方法的执行
        2)、根据ProxyFactory对象获取将要执行的目标方法拦截器链;
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            1)、List<Object> interceptorList保存所有拦截器
                一个默认的ExposeInvocationInterceptor 和 配置的增强器;
            2)、遍历所有的增强器,将其转为Interceptor;
                registry.getInterceptors(advisor);
            3)、将增强器转为List<MethodInterceptor>;
                如果是MethodInterceptor,直接加入到集合中
                如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
                转换完成返回MethodInterceptor数组;
        3)、如果没有拦截器链,直接执行目标方法;
            retVal = methodProxy.invoke(target, argsToUse)
            拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
        4)、如果有拦截器链,把需要执行的目标对象,目标方法,
            拦截器链等信息传入创建一个 CglibMethodInvocation 对象,
            并调用 Object retVal =  mi.proceed();
        5)、拦截器链的触发过程;
            new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed()
            相当于执行了父类的org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()方法
            1)、如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器)执行目标方法;
            2)、链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;
                拦截器链的机制,保证通知方法与目标方法的执行顺序;
        public Object proceed() throws Throwable {
            //currentInterceptorIndex初始化是-1,interceptorsAndDynamicMethodMatchers拦截器链集合
            // We start with an index of -1 and increment early.
            if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                return invokeJoinpoint();
            }
            //一个一个拦截器链的取
            Object interceptorOrInterceptionAdvice =
                    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                // Evaluate dynamic method matcher here: static part will already have
                // been evaluated and found to match.
                InterceptorAndDynamicMethodMatcher dm =
                        (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
                Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
                if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                    return dm.interceptor.invoke(this);
                }
                else {
                    // Dynamic matching failed.
                    // Skip this interceptor and invoke the next in the chain.
                    return proceed();
                }
            }
            else {
                // It's an interceptor, so we just invoke it: The pointcut will have
                // been evaluated statically before this object was constructed.
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
            }
        }
# 总结
1)、 @EnableAspectJAutoProxy 开启AOP功能
2)、 @EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator
3)、AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;
4)、容器的创建流程:
    1)、registerBeanPostProcessors()注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象
    2)、finishBeanFactoryInitialization()初始化剩下的单实例bean
        1)、创建业务逻辑组件和切面组件
        2)、AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程
        3)、组件创建完之后,判断组件是否需要增强
            是:切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib);
5)、执行目标方法:
    1)、代理对象执行目标方法
    2)、CglibAopProxy.intercept();
        1)、得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
        2)、利用拦截器的链式机制,依次进入每一个拦截器进行执行;
        3)、效果:
            正常执行:前置通知-》目标方法-》后置通知-》返回通知
            出现异常:前置通知-》目标方法-》后置通知-》异常通知
  • 拦截器链执行过程

拦截器返回通过

  • 拦截器链

  • 增强器 InstantiationModelAwarePointcutAdvisor接口的的实例InstantiationModelAwarePointcutAdvisorImpl

动态代理创建

org.springframework.aop.framework.DefaultAopProxyFactory创建代理
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (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.");
		}
		//如果实现了接口或者已经是代理类
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);//JDK动态代理
		}
		return new ObjenesisCglibAopProxy(config);//Cglib动态代理
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

 

	AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
		refresh();
	}
		⬇️
	//实例化剩下的不是懒加载的 单实例Bean
	finishBeanFactoryInitialization(beanFactory); 
		⬇️
	beanFactory.preInstantiateSingletons();
		⬇️
	// ? 构造器执行,创建一个Bean
	getBean(beanName);
		⬇️
	doGetBean
		⬇️
	getSingleton
		⬇️
	doCreateBean{
		//将需要Autowired 的属性方法执行一遍
		populateBean(beanName, mbd, instanceWrapper);

		initializeBean(beanName, exposedObject, mbd){
			 // aware 方法执行,给实现了xxAware的方法设置值
			invokeAwareMethods(beanName, bean); 
			applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName){
				beanProcessor.postProcessBeforeInitialization(result, beanName){
					invokeAwareInterfaces(bean){
						((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
					}
				}
			}
			// 初始化方法,执行init
			invokeInitMethods(beanName, wrappedBean, mbd);
			applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
	}

 

posted on 2021-01-27 09:21  1763392456  阅读(138)  评论(0编辑  收藏  举报

导航