面试题总结
第1章 Spring相关
1.1 什么是控制反转(IOC)?什么是依赖注入?
控制反转是应用于软件工程领域中的,在运行时被装配器对象来绑定耦合对象的一种编程技巧,对象之间耦合关系在编译时通常是未知的。在传统的编程方式中,业务逻辑的流程是由应用程序中的早已被设定好关联关系的对象来决定的。在使用控制反转的情况下,业务逻辑的流程是由对象关系图来决定的,该对象关系图由装配器负责实例化,这种实现方式还可以将对象之间的关联关系的定义抽象化。而绑定的过程是通过“依赖注入”实现的。
控制反转是一种以给予应用程序中目标组件更多控制为目的设计范式,并在我们的实际工作中起到了有效的作用。
依赖注入是在编译阶段尚未知所需的功能是来自哪个的类的情况下,将其他对象所依赖的功能对象实例化的模式。这就需要一种机制用来激活相应的组件以提供特定的功能,所以依赖注入是控制反转的基础。否则如果在组件不受框架控制的情况下,框架又怎么知道要创建哪个组件?
依然注入有以下三种实现方式:
案例:
public class AccountServiceImpl implements AccountService {
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl() {
}
//通过构造函数注入
public AccountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public void saveAccount() {
System.out.println("调用accountService");
System.out.println(name+"今年"+age+"岁了,出生日期:"+birthday);
}
//set方法
public void setName(String name) {
this.name = name;
}
//set方法
public void setAge(Integer age) {
this.age = age;
}
//set方法
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
1.1.1构造器注入
<!--
构造函数注入(不是调用无参构造函数)
name方式指定构造函数入参
-->
<bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl">
<!--
调用对应的构造函数创建实例
name:是指定当前要调用的构造函数的入参名字
value:指定入参的值
-->
<constructor-arg name="name" value="小黑"></constructor-arg>
<constructor-arg name="age" value="22"></constructor-arg>
<constructor-arg name="birthday" ref="date"></constructor-arg>
</bean>
<!--
构造函数注入(不是调用无参构造函数)
index指定对应构造函数的入参下标
-->
<bean id="accountService3" class="com.itheima.service.impl.AccountServiceImpl">
<!--
调用对应的构造函数创建实例
name:是指定当前要调用的构造函数的入参名字
value:指定入参的值
-->
<constructor-arg index="0" value="小红"></constructor-arg>
<constructor-arg index="1" value="23"></constructor-arg>
<constructor-arg index="2" ref="date"></constructor-arg>
</bean>
<!--
构造函数注入(不是调用无参构造函数)
type指定构造函数的参数类型
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<!--
调用对应的构造函数创建实例
name:是指定当前要调用的构造函数的入参名字
value:指定入参的值
-->
<constructor-arg type="java.lang.String" value="小红"></constructor-arg>
<constructor-arg type="java.lang.Integer" value="23"></constructor-arg>
<constructor-arg type="java.util.Date" ref="date"></constructor-arg>
</bean>
1.1.2 Setter方法注入
<!--
1)属性注入
-->
<bean id="accountService1" class="com.itheima.service.impl.AccountServiceImpl"
p:age="21">
<!--
property:表示给当前要创建实例的对象的对应属性注入值
name:表示调用set[name]方法 name="name"表示调用setName()方法
value:表示调用指定方法所需要的入参
-->
<property name="name" value="夏红"></property>
<!-- <property name="age" value="20"></property>-->
<!--
Date的引用
如果引用另外一个Bean则用ref
-->
<property name="birthday" ref="date"></property>
</bean>
<!--构建一个Date的实例-->
<bean class="java.util.Date" id="date"></bean>
接口注入
1.2 BeanFactory和ApplicationContext有什么区别?
BeanFactory:
是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
ApplicationContext:
应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;
区别:
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;
ApplicationContext在启动的时候就把所有的Bean全部实例化了。
延迟实例化的优点:(BeanFactory)
应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;
不延迟实例化的优点: (ApplicationContext)
-
所有的Bean在启动的时候都加载,系统运行的速度快;
-
在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题
-
建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)
1.3 Spring中单利和多例的生命周期
/*****
* 测试获取IOC容器中对应的Bean的实例
*
* 单利生命周期:
* 创建时间:程序运行时,容器加载则立刻创建单利对象的实例
* 存活时间:容器如果一直存在,则对象的实例一直存在
* 销毁时间:容器销毁时,则对象实例销毁
*
*
* 多例模式生命周期:
* 创建时间:当需要使用指定对象时,则对象创建
* 存活时间:当对象被调用时,就一直存活着
* 销毁时间:销毁由java的垃圾回收机制回收
*
*/
@Test
public void testScope(){
//创建Spring的容器对象,参数是指Spring的核心配置文件beans.xml
ClassPathXmlApplicationContext act = new ClassPathXmlApplicationContext("beans.xml");
//获取对应的实例
AccountService accountService1 = (AccountService) act.getBean("accountService");
accountService1.saveAccount();
//销毁当前容器
act.close();
}
@Test
public void testsingleton(){
SingletonInfo singletonInfo1 = SingletonInfo.newInstance();
SingletonInfo singletonInfo2 = SingletonInfo.newInstance();
System.out.println(singletonInfo1 == singletonInfo2);
}
1.4 Spring中对象实例化的3种方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
Bean的实例化方式有3种:
1)调用无参构造函数
2)调用静态工厂创建
3)调用普通工厂创建
-->
<!--
1)调用无参构造函数
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
-->
<!--
2)调用静态工厂创建
2.1)必须创建静态工厂
2.2)调用静态工厂的方法实现对象的创建,创建的对象取决于静态方法
class:表示静态工厂的全限定名
factory-method:表示创建对象的方法名
<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="createAccountService"></bean>
-->
<!--
3)调用普通工厂创建
3.1)创建普通工厂Bean对象
3.2)调用创建好的普通工厂的指定方法实现创建对应的Bean
-->
<!--创建普通工厂的Bean对象实例-->
<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"/>
<!--通过普通工厂方法创建AccountServiceImpl实例-->
<bean id="accountService" factory-method="createAccountService" factory-bean="instanceFactory"></bean>
</beans>
评论区