Spring IOC , DI 和 应用分层
应用分层
应用分层是开发中的一种思路,将应用程序设置为不同的层次,每一层各施其职,可以减少代码的耦合,多个层次共同完成程序的功能。SpringMVC其实就是应用分层的一种实现。把整体的系统分成了 Model(模型), View(视图)和Controller(控制器)三个层次,也就是将⽤户视图和业务处理隔离开,并且通过控制器连接起来,很好地实现了表现和逻辑的解耦。
但是现在将前后端分离,后端不需要关系用户的视图,所以就有了一种新的分层:把整体架构分为表现层、业务逻辑层和数据层. 这种分层⽅式也称之为"三层架构"。
这里的分层和MVC之间的关系
我认为这样的分成虽然不是正常的MVC实现,但是和MVC之间并没有什么冲突,只是实现的方法不一样,所以本质上还是一样的,⼆者的⽬的是相同的, 都是解耦,分层,代码复⽤。
IOC容器
常说Spring是一个包含众多工具方法IOC容器,IOC其实在前面就接触过,例如在类上添加@Controller和@RestController注解就是将对象交给Spring进行管理,当Spring框架启动时就会加载该类,将类交给Spring进行管理就是IOC的思想。
IOC(Inversion of Control)控制反转,也就是将控制权进行反转,本来我们需要自己进行初始化对象,但是当我们交给第三方进行管理的时候,此时我们就不需要自己去new对象了,我们只需要进行依赖注入(DI)就可以拿的这个对象的实例了。
IOC程序开发
当我们创建了一个对象的时候,在别处要使用这个对象的实例时,此时我们就可以通过加注解的方式将对象交给Spring进行管理。将这个对象交给Spring进行管理,在我们需要这个对象的实例的时候,再将它通过依赖注入的方式进行使用,这就是IOC程序开发的主要思想。
而我们通常需要将多个对象交给Spring进行管理,此时就将Spring称为一个IOC容器。
DI介绍
IOC和DI的使用
我们可以通过上面的应用分层思想实现,首先我们可以定义一个Bookcontroller层,bookDao层,Bookservice层,就可以有这样的实现:
controller:
@RequestMapping("/book")
@RestController
public class BookController {
//注入bookservice@Autowiredprivate BookService bookService;}
Bookservice:
@Component
//这个注解是将BookService放入到IOC容器中
public class BookService {//注入bookDao层@Autowiredprivate BookDao bookDao;
}
BookDao:
@Componentpublic class BookDao {
}
这样就完成了应用的分层,同时我们用通过IOC和DI完成这些层的解耦。
IOC详解
Bean存储
Controller注解(控制器存储)
我们通过Conteoller注解可以将对象放入,我们也可以将它从上下文中取出
@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象,UserControlle是放入IOC中的对象UserController userController = context.getBean(UserController.class);//使⽤对象userController.sayHi();}
}
@Service(服务存储)
@Service
public class UserService {public void sayHi(String name) {System.out.println("Hi," + name);
}
我们注入之后同样可以通过上面的方式获取。
@Repository(仓库存储)
@Repository
public class UserRepository {public void sayHi() {System.out.println("Hi, UserRepository~");
}
@Component(组件存储)
@Configuration(配置存储)
可以看到他们都是相同的功能,那么为什么不把它们合为一个呢,这个也是前⾯讲的应⽤分层是呼应的. 让程序员看到类注解之后,就能直接了解当前类的⽤途。
DI详解
DI也有多种方式:属性注⼊,构造⽅法注⼊,Setter 注⼊
构造方法注入:
@Controller
public class UserController2 {//注⼊⽅法2: 构造⽅法private UserService userService;@Autowiredpublic UserController2(UserService userService) {this.userService = userService;}
@Controller
public class UserController3 {//注⼊⽅法3: Setter⽅法注⼊private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}
Autowired注解的优点是简单快捷;缺点是不能注入除IOC容器的其他容器且不能注入一个Final修饰的属性。
构造方法注入可以注入Final修饰的,注入的对象不能被修改,通用性好构造方法是JDK支持的;但是当有多个对象时代码就会非常繁琐。
Setter注入可以在注入后再进行修改操作 ;不能注入一个Final修饰的属性,而且会有set方法被调用修改的风险。
@Autowird 与 @Resource的区别
@Controller
public class UserController {
//使用bean名称注入@Resource(name = "user2")private User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}