IoC和DI
要使用IoC功能就要导入4个Spring的核心容器的jar包:spring-beans、spring-core、spring-context、spring-expression。反转控制(IoC)是控制创建对象的方法,即以前创建对象的工作由开发人员进行,现在将对象创建和依赖关系反转给了Spring进行完成。Spring会根据配置文件对对象进行创建、依赖管理和属性注入。
简单来说,就是创建对象并赋初值,将对象存入Spring仓库等待调用,这样就不必每次调用都创建对象消耗内存了。
- 创建对象:如何创建、什么时候创建、创建几个、什么时候销毁——由Spring创建,要创建的对象将它的类名写在配置文件Bean标签中就创建,写几个创建几个。默认在容器初始化时创建,默认创建一个(单例),默认在容器销毁时销毁,以上可以通过Bean的scope属性修改。
- 依赖管理:依赖就是对象属性也是一个(自定义)对象,两个对象的类是相互依赖的。依赖由ref属性进行连接。
属性注入:就是给属性赋初值。初始化属性可以通过Set方法、构造器和p标签三种方式进行。
基于配置文件的对象创建
默认在创建容器时创建对象。容器可以创建一个类型对象,也可以创建多个类型对象,只要id不同即可。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
// 最简单的一种创建对象方式
<bean class="com.briup.spring.bean.Student" id="student"></bean>
// 基于工厂的创建对象方式
<bean class="com.briup.spring.bean.StudentFactory" id="stuFact" factory-method="getStudent"></bean>
<bean class="com.briup.spring.bean.StudentFactory" id="fact"></bean> // 静态工厂
<bean id="stuFactInstance" factory-method="getStudent2" factory-bean="fact"></bean> // 实例工厂
// 属性赋值之Set方法
<bean id="h" class="com.briup.spring.bean.Student">
<property name="id" value="11"></property>
<property name="name" value="lisi"></property>
<property name="salary" value="105.6"></property>
<property name="wife" ref="w"></property>
</bean>
<bean id="w" class="com.briup.spring.bean.Student2">
<property name="id" value="11"></property>
<property name="name" value="lisi"></property>
<property name="salary" value="105.6"></property>
</bean>
// 属性赋值之构造器
<bean id="c" class="com.briup.spring.bean.Student">
<constructor-arg name="id" value="11"></constructor-arg>
<constructor-arg name="name" value="lisi"></constructor-arg>
<constructor-arg name="salary" value="105.6"></constructor-arg>
<constructor-arg name="wife" ref="w"></constructor-arg>
</bean>
<bean id="d" class="com.briup.spring.bean.Student2">
<constructor-arg name="id" value="11"></constructor-arg>
<constructor-arg name="name" value="lisi"></constructor-arg>
<constructor-arg name="salary" value="105.6"></constructor-arg>
</bean>
// 属性赋值之p标签,需要引入p命名空间约束
<bean id="hunsband" class="com.briup.ioc.Hunsband" p:id="1" p:name="lisi" p:salary="18.9" p:date-ref="now"></bean>
<bean id="now" class="java.util.Date"></bean>
</beans>
ApplicationContext app = new ClassPathXmlApplicationContext("applictionContext.xml");
Student stu = (Student) app.getBean("student"); // 根据id创建对象,适合多个该类型对象时创建
Student student = app.getBean(Student.class); // 根据类的全类名创建对象,适合单个该类型对象创建
ApplicationContext实现了BeanFactory的接口,BeanFactory是Spring的顶层接口。
BeanFactory在创建容器时不会创建对象,而ApplicationContext在创建容器时会创建对象。
- ClassPathXmlApplicationContext是根据全类名创建。
- FileSystemXmlApplicationContext是根据配置文件在磁盘中的绝对路径创建。
- AnnotationConfigApplicationContext则是根据注解和配置类创建。
基于注解的对象创建
半注解
半注解依旧需要配置文件,但配置文件只是指明加入容器的类的对象,即这些类所在的包名,以及配置依赖关系。
半注解的配置文件如下:
使用的注解是下面全注解方式中的Bean(pojo)类注解。// 在beans添加一个约束:
xmlns:context="http://www.springframework.org/schema/context"
// 指明要扫描的包,该包和子包下的类会被创建对象放到容器中
<context:component-scan base-package="com.briup.annataion"></context:component-scan>
全注解
自Spring 5起,可以使用全注解方式。要使用全注解方式,需要导入spring-aop的jar包。将一个类变为配置类代替配置文件即可使用全注解方式,从而不必使用配置文件:
配置类注解:
@Configuration
:指明当前类是配置类;@ComponentScan(package)
:指明当前包或特定位置下的包及子包下的类是Bean类;@Bean
:指明将该方法的返回值放入Spring容器中,能够被其它Bean类所依赖;@PropertySource
:加载配置文件,可以使用${key}
调用文件的value值;@Import:
导入其它配置类。- Bean(pojo)类注解:
@Component
、@Controller
、@Service
、@Repository
:功能一样,但语义不同,分别指明该类为Bean、Web、Service、Dao层的对象;@Scope
:指定Bean类的生命周期,可以为singleton单例、prototype多例、request、session、golbal session;@Value(value)
:为属性使用Set方法赋值;@Autowaired
:根据属性类型从容器调用合适的对象自动赋值;@Qualifier(value)
:为Autowaired指明一个id,也可以用在方法的参数上;@Resource(name)
:按照容器内对象的id注入;@PostConstruct
:指定该方法在对象初始化时调用;@PostDestroy
:指定该方法在对象销毁时调用。生命周期
容器中对象的生命周期:单例为默认的生命周期,在容器创建时创建(如果是BeanFactory则是在调用时创建),容器销毁时销毁。多例基本一样,但不会调用销毁时要调用的方法(destroy方法)。request、session、golbal session则是将对象存入这些对象中,且与这些对象的生命周期相同,其中golbal session指的是集群中全局session。测试
Spring使用了容器存储对象,但每次测试都需要读取配置文件、创建容器、创建对象;如果测试类的成员变量使用了@Autowaired
之类的注解,但此时又没创建容器,就十分麻烦;诸如此类不方便测试的问题接踵而至。故Spring整合了JUnit,能够方便地进行测试。要进行测试,要导入test包和JUnit包。JUnit的版本可以是4,也可以是5,但导入的类不同。
测试方式:
JUnit4:在正常配置配置文件或配置类后,在测试类添加注解:@RunWith(SpringJUnit4ClassRunner.class)
或@RunWith(SpringRunner.class)
,以及@ContextConfiguration(classes=TestConfig.class)
即可,其中location
是配置文件路径,classes
是配置类全类名数组。
JUnit5:在正常配置配置文件或配置类后,在测试类添加注解:@ExtendWith(SpringExtension.class)
和@ContextConfiguration(classes=TestConfig.class)
;或@SpringJUnitConfig(classes = TestConfig.class)
。