Spring之IOC与DI
【概念】
什么是IOC?
Inversion of Control,即控制反转
将创建对象的控制权(控制),交给spring去创建并且管理(反转)
什么是DI?
Dependency Injection,即依赖注入
将创建好的对象通过注入维护关系
解释:
使用spring创建的对象,通常都是单例模式。假设有两个类是组合关系,类B是类A的成员变量,若我们要用到A中的B,那么是否要每一个A对象都实例化一个类B呢?当类A处于单例模式的时候效率最高的时候,这种做法是不合适的。
于是spring采用了注入,将处于单例模式的A注入到B中,从而提高效率。
【用法】
IOC和DI存在3种开发模式:
- 纯xml形式
- 半注解形式
- 全注解形式
其中,半注解模式 属于过渡期的产物,就不多做介绍了,重点介绍纯xml形式和全注解形式。
一、纯xml形式
1.新建maven项目
2.通过pom.xml导入相关依赖(所需的jar包)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.neusoft</groupId>
<artifactId>SpringDemo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringDemo1</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.创建测试类,包括Dao层的User,UserDao类
User.java
package com.neusoft.SpringDemo1.bean;
import org.springframework.stereotype.Repository;
@Repository
public class User {
private String userName;
public User() {
System.out.println("constructor User");
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
}
UserDao.java
package com.neusoft.SpringDemo1.Dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.neusoft.SpringDemo1.bean.User;
@Repository("ud")
public class UserDao {
@Autowired
private User user;
public UserDao(){
System.out.println("contructor UserDao");
}
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}
4.创建配置文件 app.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean name="userDao" class="com.neusoft.SpringDemo1.Dao.UserDao" scope="singleton">
<property name="user" ref="user"></property>
</bean>
<bean name="user" class="com.neusoft.SpringDemo1.bean.User">
<property name="userName" value="李四"></property>
</bean>
</beans>
bean:创建对象
id:给对象取名,从容器中拿的时候会用到
class:类的全路径,用于给spring去反射生成对象
scope:使用什么模式创建对象
singleton:单例
prototype:多例
property:给属性赋值
name:属性名
value:给普通属性赋值,int,String等等
ref:给成员变量是对象赋值,其他引用对象
//value实现普通属性的注入
//ref实现引用对象的注入
5.测试
Test.java
package com.neusoft.SpringDemo1.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.neusoft.SpringDemo1.Dao.UserDao;
import com.neusoft.SpringDemo1.bean.User;
public class Test1 {
public static void main(String[] args) {
//获取配置文件信息
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
//spring通过反射创建实例
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
//输出通过配置文件注入的String属性
System.out.println(userDao.getUser().getUserName());
}
}
一、全注解形式
1.新建maven项目
2.通过pom.xml导入依赖
3.创建配置文件app.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置自动扫包 -->
<context:component-scan base-package="com.neusoft.SpringDemo1"/>
</beans>
4.创建测试类(使用注解配置bean,使用注解进行注入)
4.1 使用注解配置bean有4种形式:
- Component,注解在类上,上spring创建对象
- Respository,注解在dao层
- Service,注解在service层上
- Controller,注解在Controller层上(即servlet)
四种注解在效果上没有区别,只是语义不同,可提高代码可读性
若使用注解时,形式为:
@Component、@Respository、@Service、@Controller,则其bean对象名字默认为类名首字母小写。
若采用@Respository(“test”),则其bean对象名字为设置内容。
4.2 注入有2种形式
- @Autowired,自动注入
- @Resorce
二者的区别:
Autowired是spring提供的注解,Resource是jdk提供的注解。
Autowired采用按类型注入,搭配@Qualifier(“name”)注解可以按名字注入
@Autowired(required = false)表示当找不到注入内容时,不必须注入,但会抛出空指针异常。
Resource按照属性名去注入,使用@Resource(“name”)可以按名字注入,找不到名字再按照类型注入
注意:当注入的属性为接口时,且其实现类有多个,必须要指定名字注入。
测试代码:
UserServlet.java
package com.neusoft.SpringDemo1.Controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserServlet {
public UserServlet(){
System.out.println("constructor UserServlet");
}
}
UserDaoInte.java
package com.neusoft.SpringDemo1.Dao;
public interface UserDaoInte {
void add();
}
UserImpl1.java
package com.neusoft.SpringDemo1.Impl;
import org.springframework.stereotype.Repository;
import com.neusoft.SpringDemo1.Dao.UserDaoInte;
@Repository
public class UserImpl1 implements UserDaoInte{
@Override
public void add() {
System.out.println("this is UserImpl1");
}
}
//public class UserImpl1{
//
//
//}
UserImpl2.java
package com.neusoft.SpringDemo1.Impl;
import org.springframework.stereotype.Repository;
import com.neusoft.SpringDemo1.Dao.UserDaoInte;
@Repository
public class UserImpl2 implements UserDaoInte{
@Override
public void add() {
System.out.println("this is UserImpl2");
}
}
//public class UserImpl2{
//
//
//}
UserService.java
package com.neusoft.SpringDemo1.Service;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import com.neusoft.SpringDemo1.Dao.UserDaoInte;
@Service
public class UserService {
// @Autowired(required=false)
@Autowired
@Qualifier("userImpl1")
// @Resource(name="userImpl2")
private UserDaoInte userDaoInte;
public UserService(){
System.out.println("constructor UserService");
}
public void add(){
userDaoInte.add();
}
public UserDaoInte getUserDaoInte() {
return userDaoInte;
}
public void setUserDaoInte(UserDaoInte userDaoInte) {
this.userDaoInte = userDaoInte;
}
}
5.测试
Test2.java
package com.neusoft.SpringDemo1.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.neusoft.SpringDemo1.Controller.UserServlet;
import com.neusoft.SpringDemo1.Dao.UserDao;
import com.neusoft.SpringDemo1.Service.UserService;
import com.neusoft.SpringDemo1.bean.User;
public class Test2 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
UserDao userDao = (UserDao) applicationContext.getBean("ud");
UserService userService = (UserService) applicationContext.getBean("userService");
UserServlet userServlet = (UserServlet) applicationContext.getBean("userServlet");
userService.add();
}
}
【补充内容】
一、MVC模式
- M model: 数据模型,bean,dao,service(业务层)
- V view:视图,jsp
- C controller:控制器,负责前后台交互,servlet
调用模式:
controller调用service,service调用dao
spring框架中,
spring创建userService
spring创建userDao对象
并把userDao对象注入到userService的成员属性中
二、maven依赖
2.1 pom.xml:项目构建的配置文件,在此文件中描述编译版本,所依赖的jar包等等信息,maven负责给你做依赖(即导入)
2.2 当maven中存在依赖传递 a --> b --> c
导入a时,b、c也都会导入
三、spring配置文件中对象的加载
spring配置文件中的所有对象默认在spring调用时全部实例化(无论使用xml还是标注)
但是,可以对其设置懒加载,在使用时再进行实例化。