- IoC 控制反转 Inverse of Control 创建对象的权限,Java 程序中需要用到的对象不再由程序员自己创建,而是交给 IoC 容器来创建。
- 将创建对象的权限交给了BeanFactory,这种将控制权交给别人的思想,就是控制反转 IoC。
pom.xml
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
1、使用配置文件进行类加载
Dao层
public interface HelloDao {
List<String> finaAll();
}
public class HelloDaoImpl01 implements HelloDao {
@Override
public List<String> finaAll() {
return Arrays.asList("1","2","3");
}
}
public class HelloDaoImpl02 implements HelloDao {
@Override
public List<String> finaAll() {
return Arrays.asList("4","5","6");
}
}
Service层
public interface HelloService {
List<String> findAll();
}
/**
* 耦合,使用静态工厂
*/
public class HelloServiceImpl implements HelloService{
//传入BeanName
private HelloDao helloDao= (HelloDao) BeanFactory.getDao("helloDao");
@Override
public List<String> findAll() {
return helloDao.finaAll();
}
}
Servlet层
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
private HelloService helloService=new HelloServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write(helloService.findAll().toString());
}
}
定义工厂类BeanFactory
/**
* 使用配置文件+反射的方法解耦合
*/
public class BeanFactory {
private static Properties properties;
private static Map<String,Object> cache=new HashMap<>();
static {
properties=new Properties();
//获取字节流
try {
properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("factory.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object getDao(String beanName){
//先判断缓存中是否有bean
if(!cache.containsKey(beanName)){
//双重检查
synchronized (BeanFactory.class){
if(!cache.containsKey(beanName)){
try {
String value = properties.getProperty(beanName);
Class<?> aClass = Class.forName(value);
Constructor<?> constructor = aClass.getConstructor();
Object object = constructor.newInstance();
cache.put(beanName,object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return cache.get(beanName);
}
}
factory.properties
helloDao=com.tan.dao.HelloDaoImpl01
2、Ioc 基于注解的执行原理
手写代码的思路:
1、自定义一个 MyAnnotationConfigApplicationContext,构造器中传入要扫描的包。
2、获取这个包下的所有类。
3、遍历这些类,找出添加了 @Component 注解的类,获取它的 Class 和对应的 beanName,封装成一个 BeanDefinition,存入集合 Set,这个机会就是 IoC 自动装载的原材料。
4、遍历 Set 集合,通过反射机制创建对象,同时检测属性有没有添加 @Value 注解,如果有还需要给属性赋值,再将这些动态创建的对象以 k-v 的形式存入缓存区。
5、提供 getBean 等方法,通过 beanName 取出对应的 bean 即可
参考:B站楠哥教你学Java