什么是IOC
IOC反转控制,是Spring框架的核心之一,它是一种思想,传统的开发方式就像古代小农经济,如果我们吃一个馒头,需要自己种植小麦,加工成面粉,揉面,蒸熟等各种工序,需要我们一步步控制操作,IOC就像是市场经济,只需要知道我们需要馒头,种植,加工,揉面,蒸熟等工作,都由市场进行调解,最终我们只需要付钱就可以吃到馒头。在这个场景的小农经济中,想吃馒头的人就相当于开发人员,种植等工序就相当于我们创建对象的过程,创建对象的控制权在开发人员。市场经济则是把创建对象的控制权交给了市场,市场就相当于Spring的IOC容器,这就是控制反转的一种表现。即从原来的程序员控制创建对象变成了IOC容器创建对象。
什么是DI
DI是依赖注入,是IOC思想的一种具体实现方式。我们在IOC容器中创建的bean就是依赖注入的具体表现形式。
Spring的配置文件
- 习惯上配置xml文件会命名为applicationContext.xml
- 配置文件格式如下
- applicationContext.xml
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--引入其它配置文件-->
<import resource="services.xml"/>
<!-- 给bean设置别名 -->
<alias name="test" alias="clazz" />
<!--id对应的名称需唯一-->
<!--class为完整的包名加类名-->
<bean id="itemDao" class="com.example.dao.ItemDaoImpl">
</bean>
<!-- 通过setter的方式给实例对象赋值,setter注入 -->
<bean id="test" class="com.example.dao.TestDaoImpl">
<!-- 将id为itemDao的bean创建的itemDao对象赋值给成员变量itemDao -->
<property name="itemDao" ref="itemDao"/>
<!-- 给clazz属性赋值为张三 -->
<property name="clazz" value="三年二班"/>
<!-- 给list类型的studentList属性赋值 -->
<property name="studentList">
<list>
<value>张三</value>
<value>李四</value>
</list>
</property>
<!-- 给Map类型的studentScore属性赋值 -->
<property name="studentScore">
<map>
<entry key="张三" value="88" />
<entry key="李四" value="91" />
<entry key="老师" value-ref="teacher" />
</map>
</property>
<!-- 给array类型的teachers赋值 -->
<property name="courses">
<array>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</array>
</property>
<!-- 给set类型的赋值 -->
<property name="teachers">
<set>
<value>王老师</value>
<value>李老师</value>
</set>
</property>
</bean>
<!-- 构造器注入 -->
<bean id="teacher" class="com.example.dao.Teacher">
<!-- constructor-arg为传入构造器参数 -->
<!-- name为形参名称 -->
<constructor-arg name="clazz">
<list>
<value>三年二班</value>
<value>三年一班</value>
<!-- 将值设置为空 -->
<!--错误写法<value>null</value> -->
<null />
</list>
</constructor-arg>
<!-- index为参数下标,0为第一个参数 -->
<constructor-arg index="0" value="李老师" />
</bean>
<!-- 可以创建更多的bean -->
</beans>
- services.xml
<?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">
</beans>
- ItemDao.java
package com.example.dao;
public interface ItemDao {
void sayHello();
}
- ItemDaoImpl.java
package com.example.dao;
public class ItemDaoImpl implements ItemDao{
public void sayHello() {
System.out.println("Hello Spring!");
}
}
- TestDao.java
package com.example.dao;
public interface TestDao {
}
- TestDaoImpl.java
package com.example.dao;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class TestDaoImpl implements TestDao{
ItemDao itemDao;
String clazz;
List<String> studentList;
Map<String,Integer> studentScore;
String[] courses;
Set<String> teachers;
public ItemDao getItemDao() {
return itemDao;
}
public void setItemDao(ItemDao itemDao) {
this.itemDao = itemDao;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public List<String> getStudentList() {
return studentList;
}
public void setStudentList(List<String> studentList) {
this.studentList = studentList;
}
public Map<String, Integer> getStudentScore() {
return studentScore;
}
public void setStudentScore(Map<String, Integer> studentScore) {
this.studentScore = studentScore;
}
public String[] getCourses() {
return courses;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public Set<String> getTeachers() {
return teachers;
}
public void setTeachers(Set<String> teachers) {
this.teachers = teachers;
}
@Override
public String toString() {
return "TestDaoImpl{" +
"itemDao=" + itemDao +
", clazz='" + clazz + '\'' +
", studentList=" + studentList +
", studentScore=" + studentScore +
", courses=" + Arrays.toString(courses) +
", teachers=" + teachers +
'}';
}
}
- Teacher.java
package com.example.dao;
import java.util.List;
public class Teacher {
String name;
List<String> clazz;
public Teacher(String name, List<String> clazz) {
this.name = name;
this.clazz = clazz;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", clazz=" + clazz +
'}';
}
}
- 运行 测试文件MainTest.java
package com.example.test;
import com.example.dao.ItemDao;
import com.example.dao.Teacher;
import com.example.dao.TestDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
ItemDao itemDao = (ItemDao) app.getBean("itemDao");
itemDao.sayHello();
//1.通过bean的id获取对象
TestDao testDao = (TestDao) app.getBean("clazz");
//2.通过bean的id和类型获取对象
TestDao testDao2 = app.getBean("clazz", TestDaoImpl.class);
System.out.println(testDao);
System.out.println(testDao2);
//3.通过bean的类型来获取对象,注意:根据类型获取bean时,IOC容器中有且必须有一个类型匹配的bean
Teacher teacher = app.getBean(Teacher.class);
System.out.println(teacher);
}
}
通过类型获取对象时,可以使用接口的类型进行匹配
比如将2
处代码改为
TestDao testDao2 = app.getBean("clazz", TestDao.class);
或
TestDao testDao2 = app.getBean(TestDao.class);
运行结果
Hello Spring!
TestDaoImpl{itemDao=com.example.dao.ItemDaoImpl@27ce24aa, clazz=‘三年二班’, studentList=[张三, 李四], studentScore={张三=88, 李四=91}, courses=[语文, 数学, 英语], teachers=[王老师, 李老师]}
TestDaoImpl{itemDao=com.example.dao.ItemDaoImpl@27ce24aa, clazz=‘三年二班’, studentList=[张三, 李四], studentScore={张三=88, 李四=91}, courses=[语文, 数学, 英语], teachers=[王老师, 李老师]}
Teacher{name=‘李老师’, clazz=[三年二班, 三年一班]}
以上为spring的一个基本使用方式
Spring配置中的特殊字符
空字符
null:<null />
- 正确用法
<property name="param0">
<null />
</property>
- 错误用法:使用错误写法null会被解析成字符串,比如:
<property name="param0">
<list>
<value>null</value>
</list>
</property>
<property name="param0" value="null" />
实体字符
- xml实体写法
符号 | 实体 |
---|---|
< | < |
> | > |
& | & |
' | ' |
" | " |
- 正确用法
<property name="param0" value="<骆驼祥子>" />
- 错误用法
<property name="param0" value="<骆驼祥子>" />
- CDATA
-
正确写法
<property name="param0"> <value><![CDATA[<骆驼祥子>]]></value> </property>
-
错误写法
<property name="param0" value="<![CDATA[<骆驼祥子>]]>" />
为class变量赋值
1. 引用外部的bean
<bean id="outer_example_1" class="com.example.dao.OuterExample1">
<property name="name" value="张三" />
</bean>
<bean id="example_1" class="com.example.dao.Example1">
<property name="clazz" ref="outer_example_1" />
</bean>
2. 级联
<bean id="outer_example_1" class="com.example.dao.OuterExample1">
<property name="name" value="张三" />
</bean>
<bean id="example_1" class="com.example.dao.Example1">
<property name="clazz" ref="outer_example_1" />
<property name="clazz.name" value="李四" />
</bean>
3. 引用内部bean
<bean id="example_1" class="com.example.dao.Example1">
<property name="clazz">
<bean id="inter_example_1" class="com.example.dao.OuterExample1">
<property name="name" value="张三" />
</bean>
</property>
</bean>
Array,List,Set赋值
- 常规赋值
<bean id="class_example_1">
</bean>
<bean id="array_example_1">
<!-- 为字面量赋值 -->
<property name="param0">
<!-- 如果是List,Set类型变量,将array修改为list或set即可 -->
<array>
<value>张三</value>
<value>李四</value>
</array>
</property>
<!-- 为实例变量赋值 -->
<property>
<!-- 如果是List,Set类型变量,将array修改为list或set即可 -->
<array>
<ref bean="class_example_1" />
</array>
</property>
</bean>
-
配置一个list类型的bean
- 正确用法
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> <bean id="beanDemo1" class="com.example.BeanDemo1"> </bean> <bean id="beanDemo2" class="com.example.BeanDemo2"> </bean> <bean id="Test1" class="com.example.Test1"> <property name="param0" ref="listBean" /> </bean> <util:list id="listBean"> <ref bean="beanDemo1" /> <ref bean="beanDemo2" /> </util:list> </beans>
- 错误用法
<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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--其它代码一样--> <util:list id="listBean"> <ref bean="beanDemo1" /> <ref bean="beanDemo2" /> </util:list> </beans>
和错误用法相比,正确用法分别增加了第3、6、7的约束语句
map赋值
- 常规赋值
<bean id="class_example_1">
</bean>
<bean id="map_example_1">
<!-- 为字面量赋值 -->
<property name="param0">
<map>
<entry key="学生一" value="98" />
</map>
</property>
<!-- 为实例变量赋值 -->
<property>
<map>
<entry key="学生二" value-ref="class_example_1" />
</map>
</property>
</bean>
- 配置一个map类型的bean
<util:map id="mapBean">
<entry key="学生一" value="98" />
</util:map>
使用p命名空间为变量赋值
<util:map id="mapBean">
<entry key="学生一" value="98" />
</util:map>
<bean id="testDao1" class="com.example.dao.TestDaoImpl" p:param0="三年一班" p:param1-ref="mapBean">
</bean>
引入属性文件.properties
在使用示例时先在使用maven引入以下依赖
pom.xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
下载到依赖后继续向下执行
jdbc.properties
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/spring?serverTimezone=UTC
jdbc.username = root
jdbc.password = 123456
services.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="jdbc.properties"/>
<bean id="connectMysql" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
</beans>
Test.java
package com.example.test;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.sql.SQLException;
public class Test {
public static void main(String[] args) throws SQLException {
ApplicationContext app = new ClassPathXmlApplicationContext("services.xml");
DruidDataSource druidDataSource = app.getBean(DruidDataSource.class);
System.out.println(druidDataSource.getConnection());
}
}
bean属性设置
属性名 | 属性值 | 描述 |
---|---|---|
scope:设置bean的作用域 | singleton(默认):单例模式 | 使用getbean生成对象时只会生成一个 |
prototype:多例模式 | 每调用一次getbean就会生成一个新的对象 | |
id | 自定义 | 指定bean的唯一标识 |
class | 自定义 | 指定bean需要实例化的实现类 |
init-methiod | 自定义 | 指定bean的初始化方法 |
destory-methiod | 自定义 | 指定bean的销毁方法 |
autowire | default | 自动装配的默认值(不装配) |
no | 不自动装配 | |
byType | 根据类型自动装配 | |
byName | 根据属性名装配 |
Bean的生命周期
具体实现
lifecycle.xml
<?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 id="lifeTest" class="com.example.dao.LifeDao" init-method="initMethod" destroy-method="destroyMethod">
<property name="param0" value="变量一"></property>
</bean>
</beans>
LifeDao.java
package com.example.dao;
public class LifeDao {
String param0;
public LifeDao() {
System.out.println("1.创建bean对象");
}
public LifeDao(String param0) {
this.param0 = param0;
}
public String getParam0() {
return param0;
}
public void setParam0(String param0) {
System.out.println("2.给bean对象设置属性");
this.param0 = param0;
}
@Override
public String toString() {
return "LifeTest{" +
"param0='" + param0 + '\'' +
'}';
}
public void initMethod(){
System.out.println("4.bean对象初始化");
}
public void destroyMethod(){
System.out.println("7.bean对象销毁");
}
}
LifeCycleTest.java
package com.example.test;
import com.example.dao.LifeDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class LifeCycleTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("lifecycle.xml");
classPathXmlApplicationContext.close();
}
}
输出以下内容
1.创建bean对象
2.给bean对象设置属性
4.bean对象初始化
7.bean对象销毁
当bean的scope等于prototype时,需要使用getbean时才会得到上述执行结果
后置处理器实现bean对象初始化前后的操作
MyBeanPostProcessor.java
package com.example.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("3."+beanName+"对象初始化之前");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("5."+beanName+"对象初始化之前");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
lifecycle.xml
<?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 id="lifeTest" scope="singleton" class="com.example.dao.LifeDao" init-method="initMethod" destroy-method="destroyMethod">
<property name="param0" value="变量一"></property>
</bean>
<!-- 添加后置处理器实现类 -->
<bean id="myBeanPostProcessor" class="com.example.bean.MyBeanPostProcessor"></bean>
</beans>
FactoryBean
factory.xml
<?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 class="com.example.bean.MyFactoryBean" />
</beans>
FactoryTest.java
public class FactoryTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("factory.xml");
classPathXmlApplicationContext.getBean(LifeDao.class);
}
}
注解
注解列表
注解标识 | 描述 |
---|---|
@Component | 将类标识为普通组件 |
@Controller | 将类标识为控制层组件 |
@Service | 将类标识为业务层组件 |
@Repository | 将类标识为持久层组件 |
@Autowried | 可选参数required=true/false:是否必须自动完成装配 实现自动装配功能 |
@Qualifier("Bean的id值") | 自定义bean的id值 |
扫描对应的包
<context:component-scan base-package="包路径"></context:component-scan>