欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot实战之ApplicationContext

程序员文章站 2022-10-03 11:05:26
Spring的应用程序上下文IOC依赖注入通过spring ApplicationContext实现的在受托管的组件上去声明a组件依赖b组件,ApplicationContext就会把依赖注入进去关于上下文常用的接口及其实现BeanFactory最基本的上下文接口DefaultListavleBeanFactoryApplicationContext拓展了BeanFactory,其中有对于BeanPostProcessor和BeanFactoryProcessor的自动注册功...

Spring的应用程序上下文

SpringBoot实战之ApplicationContext

IOC依赖注入

  • 通过spring ApplicationContext实现的
  • 在受托管的组件上去声明a组件依赖b组件,ApplicationContext就会把依赖注入进去

关于上下文常用的接口及其实现

  • BeanFactory
    最基本的上下文接口
    • DefaultListavleBeanFactory
  • ApplicationContext
    拓展了BeanFactory,其中有对于BeanPostProcessor和BeanFactoryProcessor的自动注册功能
    • ClassPathXmlApplicationContext
    • FileSyetemXmlApplicationContext
    • AnnotationConfigApplicationContext
  • WebApplicationContext

Web上下文层次关系

SpringBoot实战之ApplicationContext
Servlet WebApplicationContext 继承了 Root WebApplicationContext

需要注意的是,如果使用AOP对Root WebApplicationContext 中进行一些拦截,增强一些方法的功能,如果把AOP组件放在Web容器(Servlet WebApplicationContex)的CompentScan里面时是无法对其继承的父上下文(Root WebApplicationContext)做增强的.

配置Web上下文层次的方式

基于xml的

SpringBoot实战之ApplicationContext
可以看到Root Config是通过ContextLoaderListener来加载的, Servlet Config 是通过DispatcherServlet来加载的
一般会将Service和DAO的相关的配置陪在contextConfigLocation中

基于configuration的注解的方式

SpringBoot实战之ApplicationContext

context-hierarchy-demo

  • 对bean做aop的增强

在两个上下文中都定义目标Bean

@AllArgsConstructor
@Slf4j
public class TestBean {
    private String context;
	// 构造时传入context,来观察属于哪一个上下文
    public void hello() {
        log.info("hello " + context);
    }
}

切面

  • 拦截testBean打头的Bean
  • 方法执行完return后打印After hello
@Aspect
@Slf4j
public class FooAspect {
    @AfterReturning("bean(testBean*)")
    public void printAfter() {
        log.info("after hello()");
    }
}

配置类

  • 属于foo Context
  • 声明AOP切面
  • 开启对AspectJAutoProxy支持
@Configuration
@EnableAspectJAutoProxy
public class FooConfig {
    @Bean
    public TestBean testBeanX() {
        return new TestBean("foo");
    }

    @Bean
    public TestBean testBeanY() {
        return new TestBean("foo");
    }

    @Bean
    public FooAspect fooAspect() {
        return new FooAspect();
    }
}
  • applicationContext.xml
    • barContext
    • 声明一个testBean且属于Bar这个Context
  
<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/>

    <bean id="testBeanX" class="geektime.spring.web.context.TestBean">
        <constructor-arg name="context" value="Bar" />
    </bean>

    <!--<bean id="fooAspect" class="geektime.spring.web.foo.FooAspect" />-->
</beans>

主类以及xml配置

  • 主类
    • 指定从applicationContext.xml加载配置得到的barContext的父级Context是fooContext
    • 分别从fooContext和barContext取出TestBeanX观察是否被通过aop增强
    • 通过barContext从其父级fooContext取出TestBeanY观察是否被通过aop增强
@SpringBootApplication
@Slf4j
public class ContextHierarchyDemoApplication implements ApplicationRunner {

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

	@Override
	public void run(ApplicationArguments args) throws Exception {
		ApplicationContext fooContext = new AnnotationConfigApplicationContext(FooConfig.class);
		ClassPathXmlApplicationContext barContext = new ClassPathXmlApplicationContext(
				new String[] {"applicationContext.xml"}, fooContext);
		TestBean bean = fooContext.getBean("testBeanX", TestBean.class);
		bean.hello();

		log.info("=============");

		bean = barContext.getBean("testBeanX", TestBean.class);
		bean.hello();

		bean = barContext.getBean("testBeanY", TestBean.class);
		bean.hello();
	}
}

结论: 每个上下文的aop增强只会增强自己上下文中的Bean,继承关系不会影响其是否增强.

若是父子context都想选择增强,可以在父也就是RootApplicationContext中定义Aspect,然后在两个context中都开启增强

foo中

@Aspect
@Slf4j
public class FooAspect {
    @AfterReturning("bean(testBean*)")
    public void printAfter() {
        log.info("after hello()");
    }
}

bar中

<aop:aspectj-autoproxy/>

本文地址:https://blog.csdn.net/zhanghaoyu_java/article/details/109626780