或者去开发手册:http://shouce.jb51.net/spring/
或者教程网站:http://c.biancheng.net/view/4282.html
了解清楚再来看下面问题。
Bean的实例化?
答:
从本质上来说,bean定义描述了如何创建一个或多个对象实例。当需要的时候, 容器会从bean定义列表中取得一个指定的bean定义,并根据bean定义里面的配置元数据 使用反射机制来创建(或取得)一个实际的对象。
当采用XML描述配置元数据时,将通过<bean/>元素的 class属性来指定实例化对象的类型。class 属性 (对应BeanDefinition实例的 Class属性)通常是必须的(不过也有两种例外的情形,见 Section 3.2.3.2.3, “使用实例工厂方法实例化”和 Section 3.6, “bean定义的继承”)。class属性主要有两种用途 :在大多数情况下,容器将直接通过反射调用指定类的构造器来创建bean(这有点类似于 在Java代码中使用new操作符);在极少数情况下,容器将调用 类的静态工厂方法来创建bean实例,class 属性将用来指定实际具有静态工厂方法的类(至于调用静态工厂 方法创建的对象类型是当前class还是其他的class则无关紧要)。
首先介绍出BeanDefintion这个概念
现如今,我们一般获取对象的方式有两种,一种是手动直接 new;另一种是交给 Spring 管理,Spring 将管理的对象称之为 Bean,容器会先实例化 Bean,然后自动注入,实例化的过程就需要依赖 BeanDefinition。
BeanDefinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,Spring 就是根据 BeanDefinition 中的信息实例化 Bean。
三种实例化方法:
- 构造器的方式
- 静态工厂方式
- 实例化工厂方式
但是这只是实例化并不是创建
!!!关于Spring bean的创建,其本质上还是一个对象的创建,既然是对象,一定要明白一点就是,一个完整的对象包含两部分:当前对象实例化和对象属性的实例化。!!!
所以对象的实例化很简单,确也不是创建的全部步骤,但是参考下面的问题你就能大概了解整个创建了
Spring的循环依赖?
答:
在Spring中,对象的实例化是通过反射实现的,而对象的属性则是在对象实例化之后通过一定的方式设置的。
这个过程可以按照如下方式进行理解:
理解这一个点之后,对于循环依赖的理解就已经帮助一大步了,我们这里以两个类A和B为例进行讲解,如下是A和B的声明
@Component public class A { private B b; public void setB(B b) { this.b = b; } } @Component public class B { private A a; public void setA(A a) { this.a = a; } }
可以看到,这里A和B中各自都以对方为自己的全局属性。这里首先需要说明的一点,Spring实例化bean是通过ApplicationContext.getBean()方法来进行的。
如果要获取的对象依赖了另一个对象,那么其首先会创建当前对象,然后通过递归的调用ApplicationContext.getBean()方法来获取所依赖的对象,最后将获取到的对象注入到当前对象中。
这里我们以上面的首先初始化A对象实例为例进行讲解。
首先Spring尝试通过ApplicationContext.getBean()方法获取A对象的实例,由于Spring容器中还没有A对象实例,因而其会创建一个A对象
然后发现其依赖了B对象,因而会尝试递归的通过ApplicationContext.getBean()方法获取B对象的实例
但是Spring容器中此时也没有B对象的实例,因而其还是会先创建一个B对象的实例。
读者需要注意这个时间点,此时A对象和B对象都已经创建了,并且保存在Spring容器中了,只不过A对象的属性b和B对象的属性a都还没有设置进去。
在前面Spring创建B对象之后,Spring发现B对象依赖了属性A,因而还是会尝试递归的调用ApplicationContext.getBean()方法获取A对象的实例
因为Spring中已经有一个A对象的实例,虽然只是半成品(其属性b还未初始化),但其也还是目标bean,因而会将该A对象的实例返回。
此时,B对象的属性a就设置进去了,然后还是ApplicationContext.getBean()方法递归的返回,也就是将B对象的实例返回,此时就会将该实例设置到A对象的属性b中。
这个时候,注意A对象的属性b和B对象的属性a都已经设置了目标对象的实例了
上面类似一个递归的过程。
对于Spring处理循环依赖问题的方式,我们这里通过上面的流程图其实很容易就可以理解
- Spring是通过递归的方式获取目标bean及其所依赖的bean的;
- Spring实例化一个bean的时候,是分两步进行的,首先实例化目标bean,然后为其注入属性。
上面看完了bean的启动流程,在来看看ioc的启动流程
Sping事务?
答:
事务是逻辑处理原子性的保证手段,通过使用事务控制,可以极大的避免出现逻辑处理失败导致的脏数据等问题。
事务最重要的两个特性,是事务的传播级别和数据隔离级别。传播级别定义的是事务的控制范围,事务隔离级别定义的是事务在数据库读写方面的控制范围。
事务的7种传播级别,四种隔离级别
Spring配置声明式事务:
* 配置DataSource
* 配置事务管理器
* 事务的传播特性
* 那些类那些方法使用事务
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
Spring BeanFactory和FactoryBean的区别?
答:
BeanFactory
是一个接口,public interface BeanFactory
,提供如下方法:
Object getBean(String name)
<T> T getBean(String name, Class<T> requiredType)
<T> T getBean(Class<T> requiredType)
Object getBean(String name, Object... args)
boolean containsBean(String name)
boolean isSingleton(String name)
boolean isPrototype(String name)
boolean isTypeMatch(String name, Class<?> targetType)
Class<?> getType(String name)
String[] getAliases(String name)
在 Spring 中,BeanFactory
是 IoC 容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
BeanFactory
提供的高级配置机制,使得管理任何性质的对象成为可能。
ApplicationContext
是 BeanFactory
的扩展,功能得到了进一步增强,比如更易与 Spring AOP 集成、消息资源处理(国际化处理)、事件传递及各种不同应用层的 context 实现(如针对 web 应用的WebApplicationContext
)。
用的比较多的 BeanFactory
的子类是 ClassPathXmlApplicationContext
,这是 ApplicationContext
接口的一个子类,ClassPathXmlApplicationContext
从 xml 的配置文件中获取 bean 并且管理他们
例如:
public static void main(String[] args) throws Exception {
BeanFactory bf = new ClassPathXmlApplicationContext("student.xml");
Student studentBean = (Student) bf.getBean("studentBean");
studentBean.print();
}
XML配置如下:
<bean id="studentBean" class="advanced.Student">
<property name="name" value="Tom"/>
<property name="age" value="18"/>
</bean>
FactoryBean
Spring 中为我们提供了两种类型的 bean,一种就是普通的 bean,我们通过 getBean(id)
方法获得是该 bean 的实际类型,另外还有一种 bean 是 FactoryBean
,也就是工厂 bean,我们通过 getBean(id)
获得是该工厂所产生的 Bean 的实例,而不是该 FactoryBean
的实例。
FactoryBean
是一个 Bean,实现了 FactoryBean
接口的类有能力改变 bean,FactoryBean
希望你实现了它之后返回一些内容,Spring 会按照这些内容去注册 bean。
public interface FactoryBean<T>
,提供如下方法:
T getObject()
Class<?> getObjectType()
boolean isSingleton()
通常情况下,bean 无须自己实现工厂模式,Spring 容器担任工厂 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。
示例:
构造一个 FactoryBean
的实现:
public class StudentFactoryBean implements FactoryBean<Student> {
private String name;
private int age;
@Override
public Student getObject() throws Exception {
return new Student(name, age);
}
@Override
public Class<?> getObjectType() {
return Student.class;
}
/**
* 工厂所管理的对象是否为单例的
* 即如果该方法返回true,那么通过getObject()方法返回的对象都是同一个对象
*/
@Override
public boolean isSingleton() {
return true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
XML配置如下:
<bean id="studentFactoryBean" class="spring.StudentFactoryBean">
<property name="name" value="Tom"/>
<property name="age" value="28"/>
</bean>
使用:
public static void main(String[] args) throws Exception {
BeanFactory bf = new ClassPathXmlApplicationContext("student.xml");
Student studentBean = (Student) bf.getBean("studentFactoryBean");
studentBean.print();
}
Q1:IoC 是什么?
Q2:IoC 容器初始化过程?
Q3:依赖注入的实现方法有哪些?
Q4:依赖注入的相关注解?
Q5:依赖注入的过程?
Q6:Bean 的生命周期?
Q7:Bean 的作用范围?
Q8:如何通过 XML 方式创建 Bean?
Q9:如何通过注解创建 Bean?
Q10:如何通过注解配置文件?
Q11:BeanFactory、FactoryBean 和 ApplicationContext 的区别?
Spring AOP
Q1:AOP 是什么?
Q2:AOP 的相关注解有哪些?
Q3:AOP 的相关术语有什么?
Q4:AOP 的过程?