• Spring IOC


    IOC是什么

    •  IOC:控制反转,是一种设计模式。
    • 一层含义是控制权的转移,由传统的在程序中控制依赖转移到由容器来控制。
    • 第二层是依赖注入:将相互依赖的对象分离,在Spring配置文件中描述他们的依赖关系,他们的依赖关系只在使用的时候才建立,简单来说就是不需要的NEW一个对象了。

    BeanFactory

    BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

    BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。

     原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。ApplicationContext接口,它由BeanFactory接口派生而来。现在一般使用ApplicationnContext,其不但包含了BeanFactory的作用,同时还进行更多的扩展

    Note:BeanFactory和ApplicationContext创建Bean的区别

    BeanFactory延时加载,在使用到某个Bean时才会进行实例化Bean
    ApplicationConetxt在ApplicationContext对象创建时,会立即实例化单例Bean以及其依赖

     

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. http://www.springframework.org/schema/beans/spring-beans.xsd">
    6. <bean id="userDao" class="com.lb.springioc.dao.UserDaoImpl">bean>
    7. <bean id="userService" class="com.lb.springioc.service.UserServiceImpl">
    8. <property name="userDao" ref="userDao">property>
    9. bean>
    10. beans>

    Bean加载原理

    Bean实例化
    BeanDefinition对应配置文件中的标签
    BeanDefinitionReader读取配置文件所有的BeanDefinition
    BeanDefinitionRegistry将Reader读取到的BeanDefinition放在容器中

     BeanDefinition

    BeanDefinitionHolder就是持有对bean标签读取到的信息的对象

     BeanDefinitionReader

     BeanDefinitionRegistry

    自实现的IOC

    依赖

    1. <dependency>
    2. <groupId>org.projectlombokgroupId>
    3. <artifactId>lombokartifactId>
    4. <version>1.16.10version>
    5. dependency>
    6. <dependency>
    7. <groupId>dom4jgroupId>
    8. <artifactId>dom4jartifactId>
    9. <version>1.6.1version>
    10. dependency>

    实体类

    1. @Data
    2. public class BeanDefinition {
    3. private String id;
    4. private String className;
    5. private PropertyValues propertyValues;
    6. public BeanDefinition() {
    7. propertyValues = new PropertyValues();
    8. }
    9. }
    10. @Data
    11. @AllArgsConstructor
    12. @NoArgsConstructor
    13. public class PropertyValue {
    14. private String name;
    15. private String ref;
    16. private String value;
    17. }
    18. public class PropertyValues implements Iterable {
    19. private List list;
    20. public PropertyValues() {
    21. list = new ArrayList<>();
    22. }
    23. public PropertyValues add(PropertyValue propertyValue) {
    24. for (int i = 0; i < list.size(); i++) {
    25. PropertyValue value = list.get(i);
    26. if (value.getName().equals(propertyValue.getName())) {
    27. list.set(i, propertyValue);
    28. return this;
    29. }
    30. }
    31. list.add(propertyValue);
    32. return this;
    33. }
    34. public PropertyValue[] getPropertyValues() {
    35. return list.toArray(new PropertyValue[0]);
    36. }
    37. public PropertyValue geTPropertyValue(String name) {
    38. for (int i = 0; i < list.size(); i++) {
    39. PropertyValue value = list.get(i);
    40. if (value.getName().equals(name)) {
    41. return value;
    42. }
    43. }
    44. return null;
    45. }
    46. public boolean isEmpty() {
    47. return list.isEmpty();
    48. }
    49. @Override
    50. public Iterator iterator() {
    51. return list.iterator();
    52. }
    53. }

    Reader & Registry

    1. public interface BeanDefinitionReader {
    2. BeanDefinitionRegistry getRegistry();
    3. void loadResource(String location) throws Exception;
    4. }
    5. public class XmlBeanDefinitionReader implements BeanDefinitionReader {
    6. private BeanDefinitionRegistry registry;
    7. public XmlBeanDefinitionReader() {
    8. registry = new SimpleBeanDefinitionRegistry();
    9. }
    10. @Override
    11. public BeanDefinitionRegistry getRegistry() {
    12. return registry;
    13. }
    14. @Override
    15. public void loadResource(String location) throws Exception {
    16. SAXReader reader = new SAXReader();
    17. InputStream inputStream = XmlBeanDefinitionReader.class.getClassLoader().getResourceAsStream(location);
    18. Document document = reader.read(inputStream);
    19. Element rootElement = document.getRootElement();
    20. List beans = rootElement.elements("bean");
    21. for (Element bean : beans) {
    22. BeanDefinition beanDefinition = new BeanDefinition();
    23. String id = bean.attributeValue("id");
    24. beanDefinition.setId(id);
    25. beanDefinition.setClassName(bean.attributeValue("class"));
    26. PropertyValues values = new PropertyValues();
    27. List properties = bean.elements("property");
    28. for (Element property : properties) {
    29. PropertyValue value = new PropertyValue();
    30. value.setName(property.attributeValue("name"));
    31. value.setRef(property.attributeValue("ref"));
    32. value.setValue(property.attributeValue("value"));
    33. values.add(value);
    34. }
    35. beanDefinition.setPropertyValues(values);
    36. registry.registerBeanDefinition(id, beanDefinition);
    37. }
    38. }
    39. }
    1. public interface BeanDefinitionRegistry {
    2. void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
    3. void removeBeanDefinition(String beanName) throws Exception;
    4. BeanDefinition getBeanDefinition(String beanName);
    5. boolean containsBeanDefinition(String beanName);
    6. String[] getBeanDefinitionNames();
    7. int getBeanDefinitionCount();
    8. }
    9. public class SimpleBeanDefinitionRegistry implements BeanDefinitionRegistry {
    10. private Map map = new HashMap();
    11. @Override
    12. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
    13. map.put(beanName, beanDefinition);
    14. }
    15. @Override
    16. public void removeBeanDefinition(String beanName) throws Exception {
    17. map.remove(beanName);
    18. }
    19. @Override
    20. public BeanDefinition getBeanDefinition(String beanName) {
    21. return map.get(beanName);
    22. }
    23. @Override
    24. public boolean containsBeanDefinition(String beanName) {
    25. return map.containsKey(beanName);
    26. }
    27. @Override
    28. public String[] getBeanDefinitionNames() {
    29. return map.keySet().toArray(new String[0]);
    30. }
    31. @Override
    32. public int getBeanDefinitionCount() {
    33. return map.size();
    34. }
    35. }

    BeanFacoty & ApplicationContext

    1. /**
    2. * 提供BeanFactory的主要功能获取Bean
    3. */
    4. public interface BeanFactory {
    5. Object getBean(String beanName) throws Exception;
    6. T getBean(String beanName, Class clazz) throws Exception;
    7. }
    8. /**
    9. * 所有的子类对bean的创建都是非延时的
    10. */
    11. public interface ApplicationContext extends BeanFactory {
    12. /**
    13. * 加载配置文件,并创建对象
    14. * @throws Exception
    15. */
    16. void refresh() throws Exception;
    17. }
    18. public abstract class AbstractApplicationContext implements ApplicationContext {
    19. protected Map singletonMaps = new HashMap<>();
    20. protected BeanDefinitionReader beanDefinitionReader;
    21. protected String configLocation;
    22. @Override
    23. public void refresh() throws Exception {
    24. beanDefinitionReader.loadResource(configLocation);
    25. //初始化所有的bean
    26. initializationBean();
    27. }
    28. private void initializationBean() throws Exception {
    29. BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
    30. String[] beanDefinitionNames = registry.getBeanDefinitionNames();
    31. for (String beanDefinitionName : beanDefinitionNames) {
    32. BeanDefinition beanDefinition = registry.getBeanDefinition(beanDefinitionName);
    33. getBean(beanDefinition.getId());
    34. }
    35. }
    36. }
    37. public class ClassPathXmlApplicationContext extends AbstractApplicationContext {
    38. public ClassPathXmlApplicationContext(String location) {
    39. this.configLocation = location;
    40. this.beanDefinitionReader = new XmlBeanDefinitionReader();
    41. try {
    42. refresh();
    43. } catch (Exception e) {
    44. }
    45. }
    46. @Override
    47. public Object getBean(String beanName) throws Exception {
    48. Object obj = singletonMaps.get(beanName);
    49. if (obj != null) {
    50. return obj;
    51. }
    52. BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
    53. BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
    54. String clazzName = beanDefinition.getClassName();
    55. Class clazz = Class.forName(clazzName);
    56. Object bean = clazz.newInstance();
    57. PropertyValues propertyValues = beanDefinition.getPropertyValues();
    58. for (PropertyValue propertyValue : propertyValues) {
    59. //拼接set方法
    60. String name = propertyValue.getName();
    61. String setMethodName = StrUtil.filedName2SetMethodName(name);
    62. Method[] methods = clazz.getMethods();
    63. Method method = null;
    64. for (Method m : methods){
    65. if (m.getName().equals(setMethodName)){
    66. method = m;
    67. break;
    68. }
    69. }
    70. //反射创建对象
    71. String refStr = propertyValue.getRef();
    72. if (null != refStr && !"".equals(refStr)) {
    73. Object refObj = getBean(refStr);
    74. method.invoke(bean, refObj);
    75. }
    76. //value是赋值的
    77. String value = propertyValue.getValue();
    78. if (null != value && !"".equals(value)) {
    79. method.invoke(bean, value);
    80. }
    81. }
    82. singletonMaps.put(beanName, bean);
    83. return bean;
    84. }
    85. @Override
    86. public T getBean(String beanName, Class clazz) throws Exception {
    87. Object obj = getBean(beanName);
    88. if (obj == null) return null;
    89. return clazz.cast(obj);
    90. }
    91. }

    测试

    将上面的项目打包,测试项目引入其依赖

    1. <dependency>
    2. <groupId>com.testgroupId>
    3. <artifactId>mySpringartifactId>
    4. <version>0.0.1-SNAPSHOTversion>
    5. dependency>

    测试代码:

    applicationContext.xml

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. http://www.springframework.org/schema/beans/spring-beans.xsd">
    6. <bean id="userDao" class="springioc.dao.UserDaoImpl">bean>
    7. <bean id="userService" class="springioc.service.UserServiceImpl">
    8. <property name="userDao" ref="userDao">property>
    9. bean>
    10. beans>
    1. import com.lb.context.ClassPathXmlApplicationContext;
    2. import springioc.dao.UserDao;
    3. import springioc.service.UserService;
    4. public class UserController {
    5. public static void main(String[] args) throws Exception{
    6. ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    7. UserDao userDao = classPathXmlApplicationContext.getBean("userDao", UserDao.class);
    8. UserService userService = classPathXmlApplicationContext.getBean("userService", UserService.class);
    9. System.out.println(userDao);
    10. System.out.println(userService);
    11. userService.add();
    12. }
    13. }

    测试结果:

     

  • 相关阅读:
    2021年中国大学生程序设计竞赛女生专场-ADGIK
    〖Docker指南⑤〗学习Dockerfile,看这一篇就够了
    STL学习笔记(随缘更新)
    VM-Linux基础操作命令
    快乐数[环类问题之快慢指针]
    动态规划算法
    Ngnix封禁IP与ip段
    力扣27.移除元素【顺序表】
    Java学习笔记5.2.2 List接口 - LinkedList类
    【算法 | 模拟No.3】leetcode 38. 外观数列
  • 原文地址:https://blog.csdn.net/qq_33753147/article/details/126680024