Spring——IOC、HelloSpring
一、关于Spring
1.简介
欢迎访问百度百科:
网址:https://baike.baidu.com/item/spring%E6%A1%86%E6%9E%B6/2853288?fr=aladdin
学习Spring时需要用到其官网
Spring官网:https://spring.io/projects/spring-framework#overview
2.优点
- Spring是一个开源的免费的框架(容器)!
- Spring是一个轻量级的、非入侵式的框架!
- 控制反转(IOC) , 面向切面编程(AOP)!
- 支持事务的处理,对框架整合的支持!
总结:Spring就是一个轻量级的控制反转(IOC) 和面向切面编程(AOP)的框架!
3.组成
二、IOC理论推导
目录图:
以前
public interface UserDao {
public void getUser();
}
public class UserDaoImpl implements UserDao {
public void getUser() {
System.out.println("获得用户数据");
}
}
public class UserDaoMySqlImpl implements UserDao {
public void getUser() {
System.out.println("MySql获取用户数据");
}
}
public interface UserService {
public void getUser();
}
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
public void getUser() {
userDao.getUser();
}
}
ublic class MyTest {
public static void main(String[] args) {
UserServiceImpl service = new UserServiceImpl();
service.getUser();
}
}
更改需求
如果此时用户想要通过Mybatis获取用户数据,此时就需要修改UserServiceImpl 业务实现类为:
public class UserServiceImpl implements UserService {
//private UserDao userDao = new UserDaoImpl();
private UserDao userDao = new UserDaoMySqlImpl();
public void getUser() {
userDao.getUser();
}
}
这时,用户的要求只能通过程序员来进行修改。
总结
在我们以前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!
这种方法的主动权在程序员手中:
采用IOC思想
public interface UserDao {
public void getUser();
}
public class UserDaoImpl implements UserDao {
public void getUser() {
System.out.println("获得用户数据");
}
}
public interface UserService {
public void getUser();
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}
public class MyTest {
public static void main(String[] args) {
UserDaoImpl userDao = new UserDaoImpl();
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(userDao);
userService.getUser();
}
}
更改需求
如果此时用户想要通过Mybatis获取用户数据,此时无需修改UserServiceImpl 业务实现类,直接在测试类中 new UserDaoMySqlImpl()类即可,就不需要程序员修改代码,而是把各种功能的类名称暴露给用户,把决定权交给用户。只需要用户自己决定改变的需求即可:
public class MyTest {
public static void main(String[] args) {
//UserDaoImpl userDao = new UserDaoImpl();
UserDaoMySqlImpl userDaoMySql = new UserDaoMySqlImpl();
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(userDaoMySql);
userService.getUser();
}
}
在业务实现类中,我们添加、使用一个Set接口实现,会发生革命性的变化!
总结
-
之前,程序是主动创建对象!控制权在程序猿手上!
-
使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象!
这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了。大大降低了系统的耦合性,可以更加专注在业务的实现上!这就是IOC 的原型!
IOC本质
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
三、HelloSpring
1.导入Spring相关jar包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- 用于测试 -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
2.编写代码
编写一个Hello实体类
public class Hello {
private String name;
//使用<bean>,必须有set方法,否则会报错
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println("Hello" + name);
}
}
编写我们的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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--name是单个bean的名称,以后进行测试调用时直接传递这个名称即可-->
<!--class是实体类-->
<bean name="hello" class="com.cm.pojo.Hello">
<!--name是实体类中的属性-->
<!--value是给这个属性赋的具体值-->
<property name="name" value="Spring"/>
</bean>
</beans>
进行测试
@Test
public void test1() {
//这里使用ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//这里要进行类型转换
//传递xml文件中bean的名称即可,得到一个对应类的实际对象
Hello hello = (Hello) context.getBean("hello");
//利用对象去调用方法
hello.show();
}
思考问题 ?
-
Hello 对象是谁创建的 ?
hello 对象是由Spring创建的。
-
Hello 对象的属性是怎么设置的 ?
hello 对象的属性是由Spring容器设置的 。
这个过程就叫控制反转 :
控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的 ;
反转 : 程序本身不创建对象 , 而是变成被动的接收对象 ;
依赖注入 : 就是利用set方法来进行注入的;
IOC是一种编程思想 , 由主动的编程变成被动的接收 。
可以通过newClassPathXmlApplicationContext去查看一下底层源码 。
-
到了现在 , 我们彻底不用在程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 ;
-
所谓的IoC,一句话搞定 : 对象由Spring 来创建、管理 、装配 !
四、IOC创建对象的方式
使用无参构造创建对象,默认!
给Hello实体类添加一个无参构造
public class Hello {
private String name;
public Hello() {
System.out.println("无参构造");
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println("Hello" + name);
}
}
测试
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("=================");
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
}
运行结果
假设我们要使用有参构造创建对象
在实体类中添加有参构造:
public class Hello {
private String name;
/*public Hello() {
System.out.println("无参构造");
}*/
public Hello(String name) {
this.name = name;
}
/*public void setName(String name) {
this.name = name;
}*/
public void show() {
System.out.println("Hello" + name);
}
}
下面修改xml文件内容即可
-
下标赋值
<!--第一种,下标赋值!--> <bean name="hello" class="com.cm.pojo.Hello"> <constructor-arg index="0" value="Spring"/> </bean>
-
类型
<!--第二种方式:通过类型创建,不建议使用!--> <bean name="hello" class="com.cm.pojo.Hello"> <constructor-arg type="java.lang.String" value="Spring"/> </bean>
-
参数名
<!--第三种,直接通过参数名来设置--> <bean name="hello" class="com.cm.pojo.Hello"> <constructor-arg name="name" value="Spring"/> </bean>
测试方法不变
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("=================");
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!