本文是作者原创,版权归作者所有.若要转载,请注明出处.
最近在看spring源码,但是spring的体系太庞大了,在这里记录一下阅读源码中遇到知识点
@PostConstruct
被注解的方法,在对象加载完依赖注入后执行
看个demo
package com.day01.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.day01") public class SpringConfig { }
IndexDao
package com.day01.service; import org.springframework.stereotype.Component; @Component public class IndexDao { public IndexDao(){ System.out.println("IndexDao 构造方法"); } }
IndexService
@Service public class IndexService { @Autowired private IndexDao indexDao; public IndexService(){ System.out.println("IndexService 构造方法"); } @PostConstruct public void init(){ System.out.println("IndexService init方法"); } public void hello(){ System.out.println("IndexService"); } }
Testday01
public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class); IndexService indexService = (IndexService) applicationContext.getBean("indexService"); indexService.hello(); }
看结果
可以看出在spring项目中,在一个bean的初始化过程中,方法执行先后顺序为Constructor > @Autowired > @PostConstruct
BeanPostProcessor
BeanPostProcessor是Spring框架的提供的一个扩展点,通过实现BeanPostProcessor接口,程序员就可插手bean实例化的过程
看demo
@Component public class TestBeanPostProcessor implements BeanPostProcessor { /** * 在bean初始化之前执行 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("indexService")){ System.out.println("indexService postProcessBeforeInitialization"); } //这里也可以产生代理对象 Proxy.newProxyInstance(),也是aop实现的原理 return bean; } /** * 初始化之后 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("indexService")){ System.out.println("indexService postProcessAfterInitialization"); } return bean; } }
运行上文的Testday01,看下结果
可以看出
===Spring IOC容器实例化Bean===
===调用BeanPostProcessor的postProcessBeforeInitialization方法===
===调用bean实例的初始化方法===
===调用BeanPostProcessor的postProcessAfterInitialization方法===
值得说明的是这个接口可以设置多个,会形成一个列表,那么如何确定他们的执行顺序呢?
Ordered和PriorityOrdered
Spring提供了Ordered和PriorityOrdered接口,来处理相同接口实现类的优先级问题
看个demo
TestBeanPostProcessor
@Component public class TestBeanPostProcessor implements BeanPostProcessor , PriorityOrdered { /** * 在bean初始化之前执行 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("indexService")){ System.out.println("indexService postProcessBeforeInitialization"); } //这里也可以产生代理对象 Proxy.newProxyInstance(),也是aop实现的原理 return bean; } /** * 在bean初始化之前执行 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("indexService")){ System.out.println("indexService postProcessAfterInitialization"); } return bean; } @Override public int getOrder() { return 100;//注意这里 } }
TestBeanPostProcessor2
@Component public class TestBeanPostProcessor2 implements BeanPostProcessor , PriorityOrdered { /** * 在bean初始化之前执行 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("indexService")){ System.out.println("indexService postProcessBeforeInitialization2"); } //这里也可以产生代理对象 Proxy.newProxyInstance(),也是aop实现的原理 return bean; } /** * 在bean初始化之前执行 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("indexService")){ System.out.println("indexService postProcessAfterInitialization2"); } return bean; } @Override public int getOrder() { return 99; } }
运行test类,看结果
这段代码的逻辑:
1. 若对象o1是Ordered接口类型,o2是PriorityOrdered接口类型,那么o2的优先级高于o1
2. 若对象o1是PriorityOrdered接口类型,o2是Ordered接口类型,那么o1的优先级高于o2
3. 其他情况,若两者都是Ordered接口类型或两者都是PriorityOrdered接口类型,调用Ordered接口的getOrder方法得到order值,order值越大,优先级越小
若2个对象中有一个对象实现了PriorityOrdered接口,那么这个对象的优先级更高。
若2个对象都是PriorityOrdered或Ordered接口的实现类,那么比较Ordered接口的getOrder方法得到order值,值越低,优先级越高
BeanFactoryPostProcessor
spring的扩展点之一:实现该接口,可以在spring的bean创建之前修改beandefinitions属性。
例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。
可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序
看个demo
@Component public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("===============TestBeanFactoryPostProcessor============"); } }
测试类
public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class); //AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(IndexService.class); IndexService indexService = (IndexService) applicationContext.getBean("indexService"); indexService.hello(); IndexService indexService2 = (IndexService) applicationContext.getBean("indexService"); System.out.println(indexService); System.out.println(indexService2); }
运行一下,看结果
可以看到,spring管理的bean默认是单例的,我们把indexService改成prototype试一下
@Component public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("===============TestBeanFactoryPostProcessor============"); BeanDefinition indexService = beanFactory.getBeanDefinition("indexService"); String scope = indexService.getScope(); System.out.println(scope);//singleton //indexService.setScope("singleton"); indexService.setScope("prototype");//设置为原型 System.out.println(scope);//singleton } }
看下结果
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口,并可以注册bean到spring容器中,一共要实现以下两个方法:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException: 该方法的实现中,主要用来对bean定义做一些改变。 void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException: 该方法用来注册更多的bean到spring容器中,详细观察入参BeanDefinitionRegistry接口,看看这个参数能带给我们什么能力。
看个demo
public class IndexService2 { private ApplicationContext applicationContext; public IndexService2(){ System.out.println("IndexService2 构造方法"); } @PostConstruct public void init(){ System.out.println("IndexService2 init方法"); } public void hello(){ System.out.println("IndexService2 hello"); } }
注意:IndexService2并没有@Component注解,说明这个类并没有交给spring管理,继续
@Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition(); genericBeanDefinition.setScope("singleton"); genericBeanDefinition.setBeanClass(IndexService2.class);//将IndexService2交给spring管理 registry.registerBeanDefinition("indexService2",genericBeanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("===============MyBeanDefinitionRegistryPostProcessor============"); } }
注意上述代码中通过BeanDefinitionRegistryPostProcessor 将IndexService2手动注册交给spring管理
运行test类
public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class); //AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(IndexService.class); IndexService indexService = (IndexService) applicationContext.getBean("indexService"); indexService.hello(); IndexService2 indexService2 = (IndexService2) applicationContext.getBean("indexService2"); System.out.println(indexService); System.out.println(indexService2); }
看结果
ApplicationContextAware
我们可以通过注解@Autowired 很简单方便获取bean,虽然这种方法很简单方便,但是有些特殊场景用不了,比如静态方法中不能使用
此时可以借助ApplicationContextAware获取bean
看个demo
@Service public class TestServiceImpl { public String hello(){ return "hello world"; } }
这里无法注入TestServiceImpl 无法使用,看demo
@Component public class ApplicationContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext = null; @Autowired private TestServiceImpl testService; /** * 实现ApplicationContextAware接口, 注入Context到静态变量中. */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ApplicationContextUtil.applicationContext = applicationContext; } /** * 获取静态变量中的ApplicationContext. */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { return (T) applicationContext.getBean(name); } /** * 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型. */ public static <T> T getBean(Class<T> requiredType) { return applicationContext.getBean(requiredType); } /*public static String test(){ String hello = testService.hello(); }*/ }
看测试类
public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class); //AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(IndexService.class); IndexService indexService = (IndexService) applicationContext.getBean("indexService"); indexService.hello(); System.out.println(indexService); /*IndexService2 indexService2 = (IndexService2) applicationContext.getBean("indexService2"); System.out.println(indexService2);*/ String testServiceImpl = ((TestServiceImpl) ApplicationContextUtil.getBean("testServiceImpl")).hello(); System.out.println(testServiceImpl); }
看结果
ok,今天就先到这里,以后有新的内容随时补充吧