Spring框架的核心思想(IOC+AOP)

前置知识

反射、注解和动态代理(引用)

github上帮助理解Spring框架的 tiny_spring 项目
tiny-spring 分析

Spring框架的核心思想

控制反转(IOC)

反射

  • 解决的问题:

    将对象的创建过程交给容器来做,在使用的时候只需要去找容器要就行

  • 控制反转的优点:
    • 利用了在Service层用多态来接收Dao对象。即使Dao实现变换了。也不用重新编译Service代码。

      • 直接在配置文件里修改
      <!--配置service对象-->
      <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl">
      </bean>
      
      • 通过替换项目中的xxxDao实现类来实现
      public class xxxServiceImpl{
              
              
        @Autowired
        private IXXXDao xxxDao;
      }
      
      • 通过容器来实现JavaBean的管理,方便程序实现。让开发者只需要关注业务代码即可。需要使用的时候只需要注入相对应的Bean。
  • IOC的实现方式
    • IOC执行过程图示

      如下图所有,可知IOC过程中的核心为BeanFactory对象和相关的配置文件

    在这里插入图片描述

  • 配置文件(xxx.xml)+ 工厂模式(BeanFactory)+反射机制

    • 配置文件(配置所有的Bean信息,以及相应的相互依赖信息)

      将实体类之间的直接相互依赖关系,配置到配置文件中。配置文件不需要编译可以直接使用。实现个个层之间的解耦和。

      <?xml version="1.0" encoding="UTF-8" ?>
      <beans>
      	<!-- 配置ServiceBean id为获取的时候的标识,通过id从容器中获取Bean。 -->    
          <!-- class 为类的全限定名,在BeanFactory中通过它来获取类对象生成实例 -->
          <bean id="transferService" class="com.lagou.edu.service.impl.TransferServiceImpl">
              <!-- 在ServiceBean中需要一个accountDao 在Factory将所有的Bean创建后,进行注入操作 -->
              <!-- name为被引用类在引用类中的成员名称。ref为被一用对象的id -->
          	<property name="AccountDao" ref="accountDao"></property>
          </bean>
          <bean id="accountDao"
        class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl">
          </bean>
      
    ```
    • 工厂模式加反射

      public class BeanFactory{
              
              
          /**
          * 工厂类的两个任务
          * 任务一:加载解析xml,读取xml中的bean信息,通过反射技术实例化bean对象,然后放到map待用
          * 任务二:提供接口方法根据id从map中获取bean(静态方法)
          */
          // 存放所有的Bean的集合key,即为Bean的id。value 为其所对应的Bean对象。
          private static Map<String,Object> map = new HashMap<>();
          
          static{
              
              
              // 读取配置文件
              InputStream resourceAsStream =
      BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
              ...
             	// 解析配置文件获取所有配置的bean
              List<Element> list = rootElement.selectNodes("//bean");
              // 遍历list 开始反射生成对象。并放到map集合中
              for(int i=0;i<list.size() ;i++){
              
              
                  String id = element.attributeValue("id");
                  String clazz = element.attributeValue("class");
                  Class<?> aClass = Class.forName(clazz);
                  Object o = aClass.newInstance();
                  map.put(id,o);
              }
              // 维护bean之间的依赖关系
              List<Element> list = rootElement.selectNodes("//property");
              // 遍历,获取对应property的父标签获取id属性。以及property的ref和name属性
              // 使用反射调用引用类的对象的Set+"name"方法。将对应的被一用Bean设置进去
          }
      }
      

面向切面编程(AOP)

动态代理

  • 定义面向切面编程(Aspect-oriented programming)

  • 动态代理的使用场景:在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是

    • 权限校验代码
    • 日志代码
    • 事务控制代码
    • 性能监控代码。
  • 底层用到的技术动态代理

    • jdk 动态代理(只能代理实现了接口的对象)
    • cglib动态代理(能代理所有类型的对象)
  • Spring中的声明式事物管理就是用到了AOP思想。在Service层代码执行一开始绑定一个用于整个线程的连接对象。Dao层执行的时候都从ThreadLocal中获取。从而来实现Sevice层控制事务。
    Spring 中的事务传播测试

猜你喜欢

转载自blog.csdn.net/u013795102/article/details/111312059