SSM授课实录-002期-Spring IoC&DI
DI的全称是Dependency Injection,中文称之为依赖注入。它与控制反转(IoC)的含义相同,只不过这两个称呼是从两个角度描述的同一个概念。
1. IoC
在使用Spring框架之后,对象的实例不再由调用者来创建,而是由Spring容器来创建,Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由应用代码转移到了Spring容器,控制权发生了反转,这就是控制反转。
2. DI
从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入。
3. 依赖注入的实现方式
3.1 setter注入
注意点:
1. 属性的setter方法
2. 类中的无参构造方法
- UserService.java
package com.liuhaolie.spring.di;
public interface UserService {
void say();
}
- UserServiceImpl.java
package com.liuhaolie.spring.di;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void say() {
userDao.say();
System.out.println("userService say hello !!!");
}
}
- UserDao.java
package com.liuhaolie.spring.di;
public interface UserDao {
void say();
}
- UserDaoImpl.java
package com.liuhaolie.spring.di;
public class UserDaoImpl implements UserDao {
@Override
public void say() {
System.out.println("userDao say hello !!!");
}
}
- 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/beans/spring-beans.xsd">
<!-- setter注入 -->
<bean id="ud1" class="com.liuhaolie.spring.di.UserDaoImpl"/>
<bean id="us1" class="com.liuhaolie.spring.di.UserServiceImpl">
<!-- setter注入
1) 在类中添加属性,并添加属性的setter方法
2) 在bean中通过property进行属性注入
注意点:类中必须要默认的无参构造方法
问:
什么时候就没有默认的无参构造方法了?
答:
java默认为每个类都提供了默认的隐式的无参构造方法;
但是,当类中写了任何一个有参数的构造方法,那么默认
提供的无参构造方法就失效了。通常为了保证类的对象可
以被其他技术(大多是框架技术,比如Spring)方便使用,
一般会在写了有参构造方法之后,额外的再提供默认的无参
构造方法(显式)。
-->
<property name="userDao" ref="ud1"></property>
</bean>
</beans>
- TestDI.java
package com.liuhaolie.spring.di;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDI {
public static void main(String[] args) {
ApplicationContext ctxt =
new ClassPathXmlApplicationContext("applicationContext.xml");
/*
* 通过类型获取bean
* 如果当前spring容器中,有多个该类型实例,此时会报错
*/
UserService userService = ctxt.getBean(UserService.class);
userService.say();
}
}
- 运行结果
3.2 构造器注入
注意点:
1. 对应参数个数的构造方法
2. 构造方法重载注意符合语法要求
- Circle.java
package com.liuhaolie.spring.di;
public class Circle {
//圆心
private Point point;
//半径
private double r;
//有参构造方法(全参构造方法)
public Circle(Point point, double r) {
this.point = point;
this.r = r;
}
@Override
public String toString() {
return "圆心=" + point + ", 半径=" + r;
}
}
- Point.java
package com.liuhaolie.spring.di;
public class Point {
private double x,y;
public Point() {
}
public Point(double x, double y) {
this.x = x;
this.y = y;
}
//getter & setter
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
@Override
public String toString() {
return "(" + x + "," + y + ")";
}
}
- 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/beans/spring-beans.xsd">
<!-- 构造器注入 -->
<bean id="c1" class="com.liuhaolie.spring.di.Circle">
<constructor-arg name="point" ref="p1"/>
<constructor-arg name="r" value="10"/><!-- 半径为10 -->
</bean>
<bean id="p1" class="com.liuhaolie.spring.di.Point">
<constructor-arg index="0" value="2"/><!-- 参数索引,从0开始计数 -->
<constructor-arg index="1" value="5"/>
</bean>
</beans>
- TestDI.java
package com.liuhaolie.spring.di;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDI {
public static void main(String[] args) {
ApplicationContext ctxt =
new ClassPathXmlApplicationContext("applicationContext.xml");
Circle c1 = ctxt.getBean(Circle.class);
System.out.println(c1);
}
}
- 运行结果
3.3 静态工厂注入
注意点:
1. 工厂的概念:创建产品
2. 只要是创建产品的类都可以宽泛的理解为工厂
3. 静态工厂注入,指的是通过工厂的静态方法返回对象
4. 既然是静态方法,实质是通过类型名进行调用,无需创建对象
- Book.java
package com.liuhaolie.spring.bean.factory;
public class Book {
// 这里仅仅为了测试对象的创建,无需添加任何属性,当然加入属性也可以
}
- BookStaticFactory.java
package com.liuhaolie.spring.bean.factory;
/**
* 静态工厂类
* @author liuhaolie
*/
public class BookStaticFactory {
/**
* 静态工厂方法
* @return Book对象(工厂思想的根本)
*/
public static Book getBook() {
return new Book();
}
}
- 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/beans/spring-beans.xsd">
<!-- 静态工厂的方式 -->
<bean id="b2" class="com.liuhaolie.spring.bean.factory.BookStaticFactory"
factory-method="getBook"/>
</beans>
- TestFactory.java
package com.liuhaolie.spring.bean.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestFactory {
public static void main(String[] args) {
ApplicationContext ctxt = new ClassPathXmlApplicationContext("applicationContext.xml");
Book b2 = (Book) ctxt.getBean("b2");
System.out.println(b2);
}
}
- 运行结果
3.4 实例工厂注入
注意点:
1. 和静态工厂不同的是,实例工厂是先需要创建工厂实例
2. 通过工厂实例再去创建其他实例
- Book.java(同上)
- BookFactory.java
package com.liuhaolie.spring.bean.factory;
/**
* 实例工厂类
* @author liuhaolie
*/
public class BookFactory {
/**
* 实例工厂方法
* @return
*/
public Book getBook() {
return new Book();
}
}
- 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/beans/spring-beans.xsd">
<!--
实例工厂创建对象,两步:1) 创建实例工厂 2)创建对象
-->
<bean id="bookFactory" class="com.liuhaolie.spring.bean.factory.BookFactory"></bean>
<bean id="b3" factory-bean="bookFactory" factory-method="getBook"></bean>
</beans>
- TestFactory.java
package com.liuhaolie.spring.bean.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestFactory {
public static void main(String[] args) {
ApplicationContext ctxt = new ClassPathXmlApplicationContext("applicationContext.xml");
Book b3 = (Book) ctxt.getBean("b3");
System.out.println(b3);
}
}
- 运行结果
4. 小结
依赖注入的四种方式:
1. setter注入
2. 构造器注入
3. 静态工厂注入
4. 实例工厂注入
END…
PS:如有不懂,请联系okeyliu@163.com,备注来源CSDN