SpringBoot实战之ApplicationContext
程序员文章站
2022-10-03 11:05:26
Spring的应用程序上下文IOC依赖注入通过spring ApplicationContext实现的在受托管的组件上去声明a组件依赖b组件,ApplicationContext就会把依赖注入进去关于上下文常用的接口及其实现BeanFactory最基本的上下文接口DefaultListavleBeanFactoryApplicationContext拓展了BeanFactory,其中有对于BeanPostProcessor和BeanFactoryProcessor的自动注册功...
Spring的应用程序上下文
IOC依赖注入
- 通过spring ApplicationContext实现的
- 在受托管的组件上去声明a组件依赖b组件,ApplicationContext就会把依赖注入进去
关于上下文常用的接口及其实现
- BeanFactory
最基本的上下文接口- DefaultListavleBeanFactory
- ApplicationContext
拓展了BeanFactory,其中有对于BeanPostProcessor和BeanFactoryProcessor的自动注册功能- ClassPathXmlApplicationContext
- FileSyetemXmlApplicationContext
- AnnotationConfigApplicationContext
- WebApplicationContext
Web上下文层次关系
Servlet WebApplicationContext 继承了 Root WebApplicationContext
需要注意的是,如果使用AOP对Root WebApplicationContext 中进行一些拦截,增强一些方法的功能,如果把AOP组件放在Web容器(Servlet WebApplicationContex)的CompentScan里面时是无法对其继承的父上下文(Root WebApplicationContext)做增强的.
配置Web上下文层次的方式
基于xml的
可以看到Root Config是通过ContextLoaderListener来加载的, Servlet Config 是通过DispatcherServlet来加载的
一般会将Service和DAO的相关的配置陪在contextConfigLocation中
基于configuration的注解的方式
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
下一篇: input 输入的一些限制说明