spring应用上下文层级关系

applicationContext中包含了业务的pojos对象还有配置的信息,spring将这些信息通过context的形式结合了在一起,由它来形成一个完整的系统,spring application context管理了所有组件的生命周期。
spring应用上下文层级关系
应用上下文一般分成两大块:一块是servlet WebApplicationContext:里面放的是与Spring mvc相关的一些bean。早期在配置componentScan会加上一些filter只要扫描controller注解的一些bean就好,在web.xml中配置其它配置文件的加载。
servlet WebApplicationContext里面放controller,root WebApplicationContext里面放service和repository。
servlet WebApplicationContext继承了root WebApplicationContext,在servlet里面找不到对应的bean时会在root里面找。

在日常开发中使用一些中间件时,中间件是通过aop来对方法进行增强从而来实现功能的。我们在配置中间件时要注意配置application上下文关系,注意是需要增强servlet WebApplication还是root WebApplication。下面我们用一个demo来理解spring上下文层级关系

我们使用springboot构建一个demo,分别用注解和xml配置的方式来创建两个applicationContext对象,其中一个上下文继承另外一个上下文,通过分别开启父类子类的aop代理来观察现象

需要增强的类

@AllArgsConstructor
@Slf4j
public class TestBean {
    private String name;

    public void print(){
        log.info("hello"+name);
    }
}

1、注解方式配置切面

@Slf4j
@Aspect     //定义为切面
public class TestAspect {
    @AfterReturning("bean(testBean*)")     //定义通知及切入点,aop增强效果是在方法执行后增加日志“after hello”
    public void after(){
        log.info("after hello");
    }
}

2、xml配置上下文

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--
    <aop:aspectj-autoproxy/>      //开启aop代理
-->

    <bean id="testBeanX" class="com.changli.applicationContext.TestBean">
        <constructor-arg name="name" value="testBeanX"/>
    </bean>

<!--
    <bean id="testAspect" class="com.changli.applicationContext.parent.TestAspect"/>    //注入切面bean
-->
</beans>

3、通过注解配置上下文

@Configuration    //定义为配置类
@EnableAspectJAutoProxy     //开启aop代理
public class ParentConfig {
    @Bean
    public TestBean testBeanX(){
        return new TestBean("testBeanX");
    }
    @Bean
    public TestBean testBeanY(){
        return new TestBean("testBeanY");
    }
    @Bean
    public TestAspect testAspect(){
        return new TestAspect();
    }
}

4、主程序

@SpringBootApplication
@Slf4j
public class ApplicationContextApplication implements CommandLineRunner {

	public static void main(String[] args) {
		SpringApplication.run(ApplicationContextApplication.class, args);
	}

	@Override
	public void run(String... args) throws Exception {
		ApplicationContext parent = new AnnotationConfigApplicationContext(ParentConfig.class);   //加载注解配置的上下文
		ClassPathXmlApplicationContext child =new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"},parent);    //加载xml配置的上下文并继承注解配置的上下文

		TestBean beanFromParent = parent.getBean("testBeanX",TestBean.class);
		beanFromParent.print();
		log.info("================================================");

		TestBean beanFromChild =child.getBean("testBeanX",TestBean.class);
		beanFromChild.print();

		beanFromChild =child.getBean("testBeanY",TestBean.class);
		beanFromChild.print();
	}
}

运行结果
spring应用上下文层级关系
程序运行结果如上图,从父类上下文中拿出的testBeanX的方法得到了增强,从子类上下文中拿出的testBeanX,由于子类中也有定义testBeanX所以不会从父类拿,子类中没有对方法进行增强,所有没有打印after hello。子类中没有定义testBeanY,所以只能从父类中拿,父类中的方法增强了的,所以打印了after hello。
同理,你还可以将父类上下文的aop代理去掉,在子类中添加。试一试看看结果是否符合你的预期呢

demo的git地址
https://github.com/struggle1to1win/applicationContext.git

注:看丁雪峰老师教学视频后的学习笔记,侵删