2. SpringIOC

什么是IOC

IOC反转控制,是Spring框架的核心之一,它是一种思想,传统的开发方式就像古代小农经济,如果我们吃一个馒头,需要自己种植小麦,加工成面粉,揉面,蒸熟等各种工序,需要我们一步步控制操作,IOC就像是市场经济,只需要知道我们需要馒头,种植,加工,揉面,蒸熟等工作,都由市场进行调解,最终我们只需要付钱就可以吃到馒头。在这个场景的小农经济中,想吃馒头的人就相当于开发人员,种植等工序就相当于我们创建对象的过程,创建对象的控制权在开发人员。市场经济则是把创建对象的控制权交给了市场,市场就相当于Spring的IOC容器,这就是控制反转的一种表现。即从原来的程序员控制创建对象变成了IOC容器创建对象。

什么是DI

DI是依赖注入,是IOC思想的一种具体实现方式。我们在IOC容器中创建的bean就是依赖注入的具体表现形式。

Spring的配置文件

  1. 习惯上配置xml文件会命名为applicationContext.xml
  2. 配置文件格式如下
  • 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" />

实体字符

  1. xml实体写法
符号实体
<&lt;
>&gt;
&&amp;
'&apos;
"&quot;
  • 正确用法
<property name="param0" value="&lt;骆驼祥子&gt;" />
  • 错误用法
<property name="param0" value="<骆驼祥子>" />
  1. 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的销毁方法
autowiredefault自动装配的默认值(不装配)
no不自动装配
byType根据类型自动装配
byName根据属性名装配

Bean的生命周期

矩形表示可控周期或需要特殊处理才能使用
表示不可控周期
3.bean对象初始化之前操作
5.bean对象初始化之后操作
6.bean对象就绪可以使用
8.IOC容器关闭
1.创建bean对象
2.给bean对象设置属性
4.bean对象初始化
7.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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值