IOC
spring的bean创建过程(粗略的)
- 读取配置
- 将各种bean的定义封装为BeanDefinition,存入到beanDefinitionMap中
- 调用
BeanFactoryPostProcessor
的postProcessBeanFactory
方法(可以自己实现BeanFactoryPostProcessor
,做到例如修改某个BeanDefinition、自己往beanDefinitionMap注册额外的BeanDefinition等事情) - 遍历beanDefinitionMap,根据beanDefinition通过反射创建实例
- 给每个bean填充属性
- 调用
BeanPostProcessor
的postProcessBeforeInitialization
方法 - 调用
InitialingBean
的afterPropertiesSet
方法 - 调用
BeanPostProcessor
的postProcessAfterInitialization
方法
Bean工厂后处理器(BeanFactoryPostProcessor)
示例(自己注册BeanDefinition)
java
@SpringBootApplication
public class SpringDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);
// 容器启动后该方法会被调用,即使MyTestBean并没有加@Component注解被扫描为bean
context.getBean("myTestBean", MyTestBean.class).test();
}
}
java
public class MyTestBean {
public void test() {
System.out.println("================ MyTestBean test method called");
}
}
java
@Component
public class MyBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("================ postProcessBeanDefinitionRegistry called");
BeanDefinition bdf = new GenericBeanDefinition();
bdf.setBeanClassName("com.example.demo.ioc.MyTestBean");
registry.registerBeanDefinition("myTestBean", bdf);
}
}
Bean后处理器(BeanPostProcessor)
java
@SpringBootApplication
public class SpringDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);;
context.getBean(MyTestBean.class).test();
}
}
java
public class MyTestBean {
public void test() {
System.out.println("================ MyTestBean test method called");
}
}
java
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MyTestBean) {
System.out.println("================ bean后处理器的before方法执行: MyTestBean");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MyTestBean) {
System.out.println("================ bean后处理器的after方法执行: MyTestBean");
}
return bean;
}
}
容器启动后打印结果:
ini
================ bean后处理器的before方法执行: MyTestBean
================ bean后处理器的after方法执行: MyTestBean
================ MyTestBean test method called
InitializingBean
实现了InitializingBean
接口的bean在填充完属性之后它的afterPropertiesSet
方法会被自动调用(在BeanPostProcessor
的before
方法之后,after
方法之前),没什么好说的
java
@Component
public class MyTestBean implements InitializingBean {
public void test() {
System.out.println("================ MyTestBean test method called");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("================ MyTestBean afterPropertiesSet method called");
}
}
容器启动后打印结果:
ini
================ bean后处理器的before方法执行: MyTestBean
================ MyTestBean afterPropertiesSet method called
================ bean后处理器的after方法执行: MyTestBean
================ MyTestBean test method called
AOP
基础示例
启动类
java
@SpringBootApplication
@EnableAspectJAutoProxy
public class SpringDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);;
context.getBean(MyAopTestBean.class).test("spring aop");
}
}
测试bean
java
@Component
public class MyAopTestBean {
public void test(String name) {
System.out.println("hi " + name);
}
}
切面配置
java
@Aspect
@Component
public class MyAspect {
@Before("execution(* com.example.demo.aop.MyAopTestBean.*(..))")
public void before() {
System.out.println("======== 前置通知执行");
}
@Around("execution(* com.example.spring_demo.aop.MyAopTestBean.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("======== 环绕通知 - before 参数:" + Arrays.toString(joinPoint.getArgs()));
joinPoint.proceed(joinPoint.getArgs());
System.out.println("======== 环绕通知 - after");
}
}
容器启动后打印结果:
diff
======== 环绕通知 - before 参数:[spring aop]
======== 前置通知执行
hi spring aop
======== 环绕通知 - after