Spring-IOC(控制反转详解及demo)
IOC(控制反转):对象的创建交给外部容器完成。
DI(依赖注入):处理对象的依赖关系。
两者区别:
控制反转:解决对象的创建问题。
依赖注入:在创建完对象之后,对象的关系的处理(set方法的注入).
用到的jar包:
spring-beans.jar,
spring-core.jar,
spring-expression.jar,
spring-context.jar,
spring-aop.jar
commons-logging.
Spring3.x之后所有的依赖包,不包含需要时,另外下载。
(一) IOC容器装配Bean(xml配置方式)
User.java
package com.hrf;
public class User {
private int id;
private String name;
}
Application.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">
<!—id标识 class类的完全限定名-—>
<bean id="user" class="com.hrf.User"></bean>
</beans>
测试:
package com.hrf;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
//得到IOC容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//原先User user=new User();
//从容器中获取对象
User user=(User)applicationContext.getBean("user");
System.out.println(user);
}
}
测试结果为:
补充:对象的创建分为单例和双例。
scope=”singleton”,默认值为单例; 再启动容器时,创建bean,整个应用只有一个对象。
scope=”prototype”,多例; 在使用到对象时才被创建。
列如:
public class User {
private int id;
private String name;
public User() {
System.out.println("调用无参构造方法");
}
}
application.xml
<bean id="user" class="com.hrf.User" scope="prototype"></bean>
public class App {
public static void main(String[] args) {
//得到IOC容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//原先User user=new User();
System.out.println("哈哈哈!");
//从容器中获取对象
User user=(User)applicationContext.getBean("user");
}
}
测试结果为:
哈哈哈!
调用无参构造方法
若改为scope=”singleton”,测试结果为:
调用无参构造方法
哈哈哈!
思考:那么我们怎么把singleton效果变为prototype效果?这就涉及到延迟创建
lazy-init=”default” 默认为false,不延迟,启动时创建。
lazy-init=”true”延迟,启动时不创建,使用时创建。
此时我们只要这样做即可
<bean id="user" class="com.hrf.User" scope="singleton" lazy-init="true"></bean>
(二) SpringIOC容器。
作用:创建对象,处理对象依赖关系。
IOC容器创建对象几种方式:
1. 调用无参构造
2. 带参数构造
3. 工厂创建对象
1) 静态方法创建对象
2) 非静态方法创建对象
1)
public class User {
private int id;
private String name;
public User() {
super();
System.out.println("调用无参构造方法");
}
}
<!-- 1.调用无参构造 -->
<bean id="user1" class="com.hrf.User"></bean>
2)
public class User {
private int id;
private String name;
public User() {
super();
System.out.println("调用无参构造方法");
}
public User(int id, String name) {
this.id = id;
this.name = name;
System.out.println("调用带参构造方法");
}
}
<!-- 2.调用有参构造 -->
<bean id="user2" class="com.hrf.User">
<constructor-arg value="01" index="0" type="int"></constructor-arg>
<constructor-arg value="hrf" index="1" type="java.lang.String"></constructor-arg>
</bean>
<!-- 3.调用有参构造,引用其它对象 -->
<bean id="s" class="java.lang.String">
<constructor-arg value="hrf2"></constructor-arg>
</bean>
<bean id="user3" class="com.hrf.User">
<constructor-arg value="02" index="0" type="int"></constructor-arg>
<constructor-arg ref="s" index="1" type="java.lang.String"></constructor-arg>
</bean>
3)
package com.hrf;
public class UserFactory {
public User getInstance(){
return new User(001,"hrf001");
}
public static User getStaticInstance(){
return new User(002,"hrf002");
}
}
<!-- 工厂创建对象 -->
<!-- 工厂的实例 -->
<bean id="userFactory" class="com.hrf.UserFactory"></bean>
<!-- 使用非静态方法创建对象 -->
<bean id="user4" factory-bean="userFactory" factory-method="getInstance"></bean>
<!-- 使用静态方法创建对象 -->
<bean id="user5" class="com.hrf.UserFactory" factory-method="getStaticInstance"></bean>
(三) 对象的依赖关系,DI依赖注入.
1. 通过构造
2. 通过set方法对属性注入
3. P名称空间
4. 自动装配(了解)
1)<!-- 通过set方法对属性注入 -->
<bean id="user6" class="com.hrf.User">
<property name="id" value="1001"></property>
<property name="name" value="hrf1001"></property>
</bean>
2)
package com.hrf.second;
public class UserDao {
public void add(){
System.out.println("---------将数据保存到数据库-----------");
}
}
package com.hrf.second;
public class UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
userDao.add();
}
}
package com.hrf.second;
public class UserAction {
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
public String add(){
userService.add();
return null;
}
}
<!-- userDao -->
<bean id="userDao" class="com.hrf.second.UserDao"></bean>-->
<!-- userService
<bean id="userService" class="com.hrf.second.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- userAction -->
<bean id="userAction" class="com.hrf.second.UserAction">
<property name="userService" ref="userService"></property>
</bean>
3)<!-- 内部bean -->
<bean id="userAction2" class="com.hrf.second.UserAction">
<property name="userService">
<bean class="com.hrf.second.UserService">
<property name="userDao">
<bean class="com.hrf.second.UserDao"></bean>
</property>
</bean>
</property>
</bean>
4) <!-- p名称空间 -->
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.hrf.second.UserDao"></bean>
<bean id="userService" class="com.hrf.second.UserService" p:userDao-ref="userDao"></bean>
<bean id="userAction3" class="com.hrf.second.UserAction" p:userService-ref="userService"></bean>
</beans>
(四)注解方式,可以简化springIOC容器的配置
使用注解步骤:
1) 引入context名称空间
2) 开启注释扫描
使用注释:
把对象加入IOC容器@Component后面不写会默认类名相同,但第一个字母小写。
处理对象的依赖关系@Resource,不同set方法了。
@Repository 在持久层使用 (Dao层)
@Service 在业务逻辑层使用 (Service层)
@Controller 在控制层 (Action层)
package com.hrf.third;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
//三种方式都可以
//@Component("userDao") 相当于<bean id="userDao" class="com.hrf.third.UserDao"></bean>
//@Component
@Repository
public class UserDao {
public void add(){
System.out.println("---------将数据保存到数据库-----------");
}
}
package com.hrf.third;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
//@Component("userService")
//@Component
@Service
public class UserService {
//@Resource(name="userDao") 相当于<property name="userDao" ref="userDao"></property>
@Resource
private UserDao userDao;
public void add(){
userDao.add();
}
}
package com.hrf.third;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
//@Component("userAction")
//@Component
@Controller
public class UserAction {
//@Resource(name="userService")
@Resource
private UserService userService;
public String add(){
userService.add();
return null;
}
}
beans4.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
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.hrf.third"></context:component-scan>
</beans>
package com.hrf.third;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans4.xml");
UserAction userAction=(UserAction)applicationContext.getBean("userAction");
userAction.add();
}
}