Sring IOC
介绍
控制反转(inverse of control) 这个不是什么技术,而是指的一种思想。它的目的是直到我们设计出更加松耦合的程序。
控制:在java中指的是对象的控制权限(创建、销毁)
反转:指的是对象控制权由原来 由开发者在类中手动控制 反转到由Spring容器控制
一句大白话:bean的创建和销毁交给spring容器管理
IOC大概的原理
pom.xml:
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
myBean.xml:
<beans>
<bean id="orderDao" class="com.llz.dao.impl.OrderDaoImpl"/>
<bean id="orderService" class="com.llz.service.impl.OrderServiceImpl"/>
</beans>
工厂类:
public class MyBeanFactory {
private static Map<String,Object> map = new HashMap<String, Object>();
static{
try {
//加载myBean.xml,解析xml,将所有的配置的内容放入到map中
//使用dom4j和xpath技术,导入这两个jar包
InputStream is = MyBeanFactory.class.getClassLoader().getResourceAsStream("myBean.xml");
Document doc = new SAXReader().read(is);
List<Element> list = doc.selectNodes("//bean");
for (Element element : list) {
//获取id和class属性
String id = element.attributeValue("id");
String classValue = element.attributeValue("class");
//使用全限定类名创建实现类对象
Object obj = Class.forName(classValue).newInstance();
//将id作为key 对象作为value放入map中
map.put(id,obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object getBean(String id){
return map.get(id);
}
}
service类:
public class OrderServiceImpl implements OrderService {
//private OrderDao orderDao = new OrderDaoImpl();
//若orderDao的实现类发生了改变,重新编写了OrderDaoImpl2类,导致service代码的改变
//private OrderDao orderDao = new OrderDaoImpl2();
//这里我们直接使用工厂模式替代
private OrderDao orderDao = (OrderDao) MyBeanFactory.getBean("orderDao");
public void save() {
System.out.println("orderServiceImpl 执行保存操作");
orderDao.save();
}
}
如上:即是springIOC的大致操作,它底层用工厂代替我们对对象进行创建和销毁。
1.Spring的IOC入门(xml方式)
需求
使用spring的ioc实现UserDao层保存操作
步骤分析及代码实现
- 导入依赖(spring-context)
- 编写UserDao接口及其实现类
- 编写一个spring的配置文件(名字任意):applicationContext.xml
- 通过bean标签配置dao
- 编写测试代码
- 获取spring容器(工厂)对象
- 通过工厂对象获取dao的对象
- 调用save方法
pom.xml
<!--导入spring的ioc核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
spring的核心配置文件,名字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 http://www.springframework.org/schema/applicationContext/spring-beans.xsd">
<bean id="userDao" class="com.llz.dao.impl.UserDaoImpl"/>
</beans>
测试类
public class TestHelloIOC {
@Test
public void testIocHello(){
//- 获取spring容器(工厂)对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//- 通过工厂对象获取dao的对象
UserDao userDao = (UserDao) context.getBean("userDao");
//- 调用save方法
userDao.save();
}
}
Spring相关API
Spring的API体系异常庞大,现在只关注两个BeanFactory和ApplicationContext
- 进入BeanFactory之后,点击ctrl+h打开体系结构图
实现类:
* FileSystemXmlApplicationContext【了解】
功能:从指定磁盘目录加载xml配置文件,创建spring的ioc容器
* ClassPathXmlApplicationContext
功能:从类路径下加载xml配置文件,创建spring的ioc容器
* AnnotationConfigApplicationContext
功能:加载注解配置类,创建spring的ioc容器
运行时常见异常
applicationContext.xml配置文件
<!--
bean:将配置的对象加入spring容器管理
id属性(name属性):给bean起个名字,要保证当前项目中唯一
class属性:配置对象对应的全限定类名(类且有无参构造器)
其他的配置:
scope属性:配置对象的作用范围(单实例还是多实例等)
常见俩值:
singleton:默认值,单实例对象
prototype:多实例对象,一般用不上,struts2框架中action是多实例
init-method属性:指定对象创建成功之后要执行的方法(初始化操作),我们一般用不上,框架底层使用
destroy-method属性:指定对象销毁之前要执行的方法(销毁操作),我们一般用不上,框架底层使用
-->
<bean id="userDao" class="com.llz.dao.impl.UserDaoImpl" scope="singleton" init-method="init" destroy-method="dest"/>
2.Spring-IOC入门(注解方式)
Spring常用注解主要是替代<bean> 的配置
<bean id="名字" class="类的全限定类名" scope="" init-method="" destory-method="">
<property name="属性名" value|ref=""/>
</bean>
spring中ioc的注解要想使用,需要先开启组件扫描
<context:component-scan base-package="com.llz"/>
使用在类上的注解
@Component:组件
- 替代bean标签,将类的产生的对象加入到spring容器中
- value属性:设置在spring容器中的名字.也可以不写名字,名字的默认值就是类名首字母小写
- 在开发中经常使用的时候它的三个衍生的注解(可以当成孩子)
@Controller:在web层的类上 (重要)
@Service:在service层的类上 (重要)
@Repository:在dao层的类上 (重要)
三个衍生的注解目前和Component一样,几乎没有区别,但是建议根据类的位置使用不同的注解
@Scope:作用域
使用在成员变量上的注解-注入
可以不给成员变量提供set方法.也可以提供set方法
注解可以作用在成员变量上,也可以作用在set方法上.
@Value
@Autowired
- 给引用类型的成员变量进行赋值.值是已经存在于spring容器中,相当于ref属性
- 默认是按照数据类型注入.
- 若只找到一个此类型的对象,直接注入
- 若找到了多个此类型的对象,把变量名作为名字去spring容器中匹配.若匹配到了直接注入;若匹配不到就会报异常
- 可以搭配使用 @Qualifier 注解,使用它的value属性指定名字进行注入(装配)
扩展:jdk也提供了一个注解 @Resource,做的事情和@Autowired及@Qualifier的作用是一样的
总结