Spring的应⽤上下⽂
在spring中,有两种定义上下⽂做aop拦截的⽅式。⼀种是使⽤Java类做⼀个⽗配置。另外⼀个就是⽤l做⼦配置。
我们在FooConfig.java 中定义两个 testBean,分别为 testBeanX(foo) 和 testBeanY(foo)。
@AllArgsConstructor
@Slf4j
public class TestBean {
private String context;
public void hello(){
log.info("hello "+ context);
}
}
@Aspect//定义⼀个切⾯
@Slf4j
public class FooAspect {
@AfterReturning("bean(testBean*)")//在你这个testBean*类成功返回之后执⾏
public void printAfter(){
log.info("after hello()");
}
}
@Configuration//@Configuration的作⽤等价于XML配置中的标签,@Bean的作⽤等价于XML配置中的标签。Spring在解析该类时,会识别出标注@Bean的所有⽅法,执⾏并将⽅法的返回值\注册到IoC容器中。默认情况下,⽅法名即为Bean的名字。
@EnableAspectJAutoProxy//开启aspectj的⽀持,对打@aspectj相关注解的类做⼀个Proxy
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();
}
}
<beans xmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance"
xmlns:aop="/schema/aop"
xsi:schemaLocation="/schema/beans
/schema/beans/spring-beans.xsd
/schema/aop
/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<bean id="testBeanY"class="geektime.t.TestBean">
<constructor-arg name="context" value="QAQ"/>
</bean>
<!--<bean id="fooAspect"class="geektime.spring.web.foo.FooAspect"/>-->
</beans>
它的委托机制为:在⾃⼰的context 中不到bean,会委托⽗context 查该bean。
运⾏代码如下:
@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);//⽤这个类加载FooConfig
ClassPathXmlApplicationContext barContext =new ClassPathXmlApplicationContext(
new String[]{"l"}, fooContext);//加载l,声明fooContext为上级Context
TestBean bean = Bean("testBeanX", TestBean.class);//在⽗上下⽂查 testBeanX,命中直接返回 testBeanX(foo)。
bean.hello();
log.info("=============");
bean = Bean("testBeanX", TestBean.class);//在⼦上下⽂查 testBeanX,命中直接返回 testBeanX(bar)。
spring aop应用场景bean.hello();
bean = Bean("testBeanY", TestBean.class);//在⼦上下⽂查 testBeanY,未命中;委托⽗上下⽂查,命中,返回 testBeanY(foo)。  bean.hello();
}
}
场景⼀
⽗上下⽂开启 @EnableAspectJAutoProxy 的⽀持
⼦上下⽂未开启 <aop: aspectj-autoproxy />
切⾯ fooAspect 在 FooConfig.java 定义(⽗上下⽂增强)
输出结果:
testBeanX(foo) 和 testBeanY(foo) 均被增强。testBeanX(foo)是⼦上下⽂没有到之后,去⽗上下⽂的
testBeanX(bar) 未被增强。
在⽗上下⽂开启了增强,⽗上下⽂的 bean 均被增强,⽽⼦上下⽂的 bean 未被增强。
场景⼆
⽗上下⽂开启 @EnableAspectJAutoProxy 的⽀持
⼦上下⽂开启 <aop: aspectj-autoproxy />
切⾯ fooAspect 在 l 定义(⼦上下⽂增加)
输出结果:
testBeanX(foo) 和 testBeanY(foo) 未被增强。
testBeanX(bar) 被增强。
在⼦上下⽂开启增强,⽗的 bean 未被增强,⼦的 bean 被增强。
从上⾯两个场景可以看出:
各个 context 相互独⽴,每个 context 的 aop 增强只对本 context 的 bean ⽣效。如果想将切⾯配置成通⽤的,对⽗和⼦上下⽂的 bean 均⽀持增强,则:
1. 切⾯ fooAspect 定义在⽗上下⽂。
2. ⽗上下⽂和⼦上下⽂,均要开启 aop 的增加,即 @EnableAspectJAutoProxy 或<aop: aspectj-autoproxy /> 的⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。