控制反转,是一种设计思想,原来我们新建一个对象,需要自己去手动new一个对象,但有了IoC,就把创建对象这个过程的控制权交给了框架来处理。
IoC 容器实际上就是个Map<key,value>,Map 中存放的是各种对象。
当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
拿一个具体的例子来体现IoC的好处,通常来说,我们的Spring Boot项目里,Controller里会有一个Service,Service里会有一个DAO,他们的关系大概是这样:
public class UserController{
private UserService userServie;
}
public class UserService{
private UserDao userDao;
}
public class UserDao{
}
如果没有了IoC,我们要使用UserContrller这个类,可能就需要这样子玩:
UserDao userDao = new UserDao();
UserService userService = new UserService(userDao);
UserController userController = new UserController(userService);
P.S.:上面的构造函数注入,也可以用setter注入。
如果没有IoC,我们就需要这样写代码。
他们三者的关系,是Controller依赖Service,Service依赖DAO。
有了IoC,我们会在一开始写好配置(比如以前Spring的XML文件,现在则完全用注解替代),有了注解,Spring就能利用反射,先找到最底层的DAO,就像我们上面的代码一样,一个个去创建对象,Spring IoC控制着创建对象的过程。具体过程如下:
这便是Spring的IoC/DI的工作过程,因为我们配置好了注解,使得这部分可以交给Spring来完成,我们无需关注过程如何,只需拿到结果即可。
这个过程中,IoC和DI的概念很容易搞混,有人说这两个不是一个概念,也有人说是。
我看到的比较好的回答是这样子的:
IoC是目的,DI是手段。
IoC是指让生成类的方式由传统方式(new)反过来,既程序员不调用new,需要类的时候由框架注入(DI)。
是同一件事不同层面的解读。
面向切面编程,能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP就是基于动态代理的。
如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象。
而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib 。
拿权限控制来举例,很多接口的访问是需要验证用户身份的,而有些不用,比如登录接口。
Spring Boot有提供一个HandlerInterceptor
接口,实现了这个接口之后会重写下面三个方法:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
像验证用户身份这些细节,不涉及具体业务,步骤都是一样的,就可以利用AOP封装起来,Spring在执行的时候,就会如下图的顺序去执行。
原文:https://www.cnblogs.com/tandk-blog/p/14817310.html