做者:小傅哥
博客:https://bugstack.cnhtml
沉淀、分享、成长,让本身和他人都能有所收获!😄
多线程、锁、JVM调优,都背出花啦,怎么一写代码仍是乱糟糟?
java
为何这些不管从书本、课堂、面试都显得很是重要的知识,可是在实际的编程中没有提高你的编码能力呢?程序员
首先这些这些知识在实际的互联网业务开发中,几乎是不经常使用的,几乎有锁和多线程的场景,为了性能的提高也基本都是采用分布式设计和实现了。而这些看上去颇有技术含量的知识多数都被包装在非业务逻辑功能的组件中,而程序员在作业务开发时候几乎是关心不到。因此会了这些也几乎不太可能就把你的编码能提高起来,多数提高的是你在查复杂bug时候有一臂之力。面试
就像会汉字就能写出诗词歌赋吗?懂RGB就能绘出山河大川吗?能蹦跳就能够舞出摇曳生姿吗?那都是不可能的,不要想着屁股围噶布就说会武术!算法
若是真的想把代码写好,就要一点点从积累数据结构和算法逻辑(不仅是机械式的刷几道题就算了。你不理解为何,刷再多也只是徒劳),接下来要作的是对设计模式和架构设计的理解,最终是不断的运用和总结。在这个过程你会接触到业务、产品、运营,编码只是最后的具体实现,并非全流程中最重要的一部分,与编码相比更重要的是逻辑设计。spring
谢飞机,小记!
,此次放假一遍撸串一遍被Spring,嘿嘿,检验成果面试去!编程
面试官:飞机,今天准备咋样,上次问你的都学会了吗?设计模式
谢飞机:@Resource 是 JDK javax.annotation.Resource
提供的注解,哈哈哈哈哈,另外也学习了Bean的注入。缓存
面试官:挺好记住了一些,那你在作 Bean 注入学习的时候,有注意到 Spring IOC 的特性吗,你都用到了什么?数据结构
谢飞机:嗯,用到 Bean 的配置、BeanDefinitionRegistryPostProcessor 对 Bean 的定义、还有 FactoryBean
面试官:好,那今天再和你聊聊,alias、autowire、depends-on、factory-method、lookup-method等,实践验证下看看它们是怎么应用的。
IOC(Inversion of Control),控制反转的核心思想在于,资源的使用不禁使用各自管理,而是交给不使用资源的第三方进行管理。这样的好处是资源是集中管理的,可配置、易维护,同时也下降了双方的依赖度作到了低耦合。
早在1988年,Ralph E. Johnson & Brian Foote在论文《Designing Reusable Classes》
One important characteristic of a framework is that the methods defined by the user to tailor the framework will often be called from within the framework itself, rather than from the user's application code.
The framework often plays the role of the main program in coordinating and sequencing application activity.
This inversion of control gives frameworks the power to serve as extensible skeletons. The methods supplied by the user tailor the generic algorithms defined in the framework for a particular application.
接下来就给你们介绍一下 IOC 的一些核心特性,由于这些内容不只是面试考点,也是在开发中间件或者小组件时须要用到的功能类,归纳以下:
测试类
public class UserService { private UserDao userDao; public UserService() { System.out.println("我被初始化了,UserService"); } // ...get/set }
xml配置
<bean id="userService" class="org.itstack.interview.UserService"/> <!-- 起个别名 --> <alias name="userService" alias="userService-alias01"/> <!-- 别名的别名 --> <alias name="userService-alias01" alias="userService-alias02"/>
单元测试
@Test public void test_alias() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-alias.xml"); logger.info("获取 Bean:{}", beanFactory.getBean("userService")); logger.info("获取 Bean 经过别名:{}", beanFactory.getBean("userService-alias01")); logger.info("获取 Bean 经过别名的别名:{}", beanFactory.getBean("userService-alias02")); }
测试结果
23:01:29.872 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean:org.itstack.interview.UserService@2a40cd94 23:01:29.872 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userService' 23:01:29.872 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean 经过别名:org.itstack.interview.UserService@2a40cd94 23:01:29.872 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userService' 23:01:29.872 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean 经过别名的别名:org.itstack.interview.UserService@2a40cd94
测试类
public class UserDao { public UserDao() { System.out.println("我被初始化了,UserDao"); } }
xml配置
<bean id="userDao" class="org.itstack.interview.UserDao"/> <!-- 手动配置依赖 --> <bean id="userService-by-property" class="org.itstack.interview.UserService"> <property name="userDao" ref="userDao"/> </bean> <!-- 自动配置依赖 --> <bean id="userService-by-autowire" class="org.itstack.interview.UserService" autowire="byName"/>
单元测试
@Test public void test_autowire() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-autowire.xml"); logger.info("获取 Bean by 手动配置依赖:{}", beanFactory.getBean("userService-by-property")); logger.info("获取 Bean by 自动配置依赖:{}", beanFactory.getBean("userService-by-autowire")); }
测试结果
23:05:55.501 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean by 手动配置依赖:org.itstack.interview.UserService@679b62af 23:05:55.501 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userService-by-autowire' 23:05:55.501 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean by 自动配置依赖:org.itstack.interview.UserService@5cdd8682
测试类
public class StaticFactoryBean { static public UserDao getUserDaoByStatic(){ return new UserDao(); } }
xml配置
<bean id="staticFactory-method" class="org.itstack.interview.StaticFactoryBean" factory-method="getUserDaoByStatic"/>
单元测试
@Test public void test_factory_method() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-method.xml"); logger.info("获取 Bean:{}", beanFactory.getBean("staticFactory-method")); }
测试结果
23:15:28.950 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean:org.itstack.interview.UserDao@588df31b 23:15:28.950 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'staticFactory-bean'
factory-method="getUserDaoByStatic"
,这样就能够在初始化时候调用对应静态方法的实例化内容。测试类
public class StaticFactoryBean { public UserDao getUserDao(){ return new UserDao(); } }
xml配置
<bean id="staticFactory" class="org.itstack.interview.StaticFactoryBean"/> <bean id="staticFactory-bean" factory-bean="staticFactory" factory-method="getUserDao"/>
单元测试
@Test public void test_factory_bean_method() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-method.xml"); logger.info("获取 Bean:{}", beanFactory.getBean("staticFactory-bean")); }
测试结果
23:15:28.950 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean:org.itstack.interview.UserDao@33b37288
factory-method="getUserDao"
调用的是对应的费静态方法返回实例化结果。xml配置
<bean id="userService" class="org.itstack.interview.UserService" depends-on="userDao"/> <bean id="userDao" class="org.itstack.interview.UserDao"/>
单元测试
@Test public void test_depends_on() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-depends-on.xml"); logger.info("获取 Bean:{}", beanFactory.getBean(UserService.class, "userService").getUserDao()); }
测试结果
我被初始化了,UserDao 我被初始化了,UserService 23:24:14.678 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean:org.itstack.interview.UserDao@45afc369
depends-on="userDao"
,那么按照 Spring 的配置最早初始化的是 UserService
,当你有须要处理初始化依赖时则须要使用到这个配置。测试类
public class UserDaoProvider implements ApplicationContextAware { private ApplicationContext applicationContext; public UserDao getUserDao() { return applicationContext.getBean("userDao", UserDao.class); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
xml配置
<bean id="userDao" class="org.itstack.interview.UserDao" scope="prototype"/> <bean id="provider" class="org.itstack.interview.UserDaoProvider"/>
单元测试
@Test public void test_lookup_method() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-lookup-method.xml"); logger.info("获取 Bean:{}", beanFactory.getBean(UserDaoProvider.class, "provider").getUserDao()); logger.info("获取 Bean:{}", beanFactory.getBean(UserDaoProvider.class, "provider").getUserDao()); }
测试结果
我被初始化了,UserDao 16:29:25.813 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'userDao' 16:29:25.813 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean:org.itstack.interview.UserDao@1188e820 16:29:25.813 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'userDao' 我被初始化了,UserDao 16:29:25.814 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'userDao' 16:29:25.814 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean:org.itstack.interview.UserDao@2f490758
scope="prototype"
配置,Spring 内部实现为使用 Cglib 方法,从新生成子类,重写配置的方法和返回对象,达到动态改变的效果。测试类
public class MyFactoryBean implements FactoryBean<UserDao> { @Override public UserDao getObject() throws Exception { return new UserDao(); } @Override public Class<?> getObjectType() { return UserDao.class; } @Override public boolean isSingleton() { return true; } }
xml配置
<bean id="userDao" class="org.itstack.interview.MyFactoryBean"/>
单元测试
@Test public void test_factory_bean() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-bean.xml"); logger.info("获取 Bean:{}", beanFactory.getBean("userDao")); }
测试结果
23:36:19.339 [main] INFO org.itstack.interview.test.ApiTest - 获取 Bean:org.itstack.interview.UserDao@3bd94634
测试类
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化前:" + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化后:" + beanName); return bean; } }
xml配置
<bean id="beanPostProcessor" class="org.itstack.interview.MyBeanPostProcessor"/> <bean id="userDao" class="org.itstack.interview.UserDao"/>
单元测试
@Test public void test_bean_post_processor() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-bean-post-processor.xml"); }
测试结果
初始化前:userDao 初始化后:userDao 16:38:32.686 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'userDao'
测试类
public class MyBeanFactoryAware implements BeanFactoryAware { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { } }