• 聊聊分布式架构07-[Spring]IoC和AOP


    目录

    Spring IoC

    IoC的设计与实现

    简单容器BeanFactory

    高级容器ApplicationContext

    IoC容器工作过程

    Spring AOP

    简单的Spring AOP示例


    Spring IoC

    IoC(Inversion of Control)IoC是一种设计原则,它反转了传统的控制流。

    • 在传统的编程中,应用程序通常负责控制对象的创建和生命周期。

    • 而在IoC中,控制权被反转,应用程序不再负责直接创建和管理对象,而是将这些职责委托给一个容器或框架。这个容器负责实例化、组装和管理对象,使得应用程序的组件更加解耦、可维护和可扩展。

    IoC的设计与实现

    Spring Ioc容器的设计中,可以看到两个主要的容器系列:简单容器BeanFactory和高级容器ApplicationContext。

    简单容器BeanFactory

    简单模拟下BeadFactory演示IoC的设计:

    1. 创建配置文件,包含BeanDefinition的信息。

      user:com.elaine.myspring.ioc.beanfactory.bean.User
    2. 创建一个BeanDefinition类,定义bean的属性。

      public class BeanDefinition {
          private String beanName;
      ​
          private Class beanClass;
      ​
          public String getBeanName() {
              return beanName;
          }
      ​
          public void setBeanName(String beanName) {
              this.beanName = beanName;
          }
      ​
          public Class getBeanClass() {
              return beanClass;
          }
      ​
          public void setBeanClass(Class beanClass) {
              this.beanClass = beanClass;
          }
      }
    3. 创建资源加载器ResourceLoader,用来加载配置文件中的配置。

      /**
       * 载入配置文件,通过BeanDefinition解析加载
       */
      public class ResourceLoader {
          public static Map getResource() {
              Map beanDefinitionMap = new HashMap<>(16);
              Properties properties = new Properties();
              try {
                  InputStream inputStream = ResourceLoader.class.getResourceAsStream("/beans.properties");
                  properties.load(inputStream);
                  // 迭代遍历配置文件
                  Iterator iterator = properties.stringPropertyNames().iterator();
                  while (iterator.hasNext()) {
                      String key = iterator.next();
                      String className = properties.getProperty(key);
                      BeanDefinition beanDefinition = new BeanDefinition();
                      beanDefinition.setBeanName(key);
                      Class clazz = Class.forName(className);
                      beanDefinition.setBeanClass(clazz);
                      // 加载资源
                      beanDefinitionMap.put(key, beanDefinition);
                  }
                  inputStream.close();
              } catch (IOException e) {
                  e.printStackTrace();
              } catch (ClassNotFoundException e) {
                  e.printStackTrace();
              }
              return beanDefinitionMap;
          }
      }
      ​
    4. 创建对象注册器BeanRegister,注册bean到container中。

      public class BeanRegister {
          // 假设所有对象都是单例的,用一个单例map缓存
          private Map singletonMap = new HashMap<>();
      ​
          /**
           * 获取单例bean
           * @param beanName
           * @return
           */
          public Object getSingletonBean(String beanName) {
              return singletonMap.get(beanName);
          }
      ​
          /**
           * 注册单例bean
           * @param beanName
           * @param bean
           */
          public void registerSingletonBean(String beanName, Object bean) {
              if(singletonMap.containsKey(beanName)) {
                  return;
              }
              singletonMap.put(beanName, bean);
          }
      }
    5. 创建对象工厂BeanFactory,初始化需要完成资源的加载,对象注册器的创建。

      public class BeanFactory {
          private BeanRegister beanRegister;
      ​
          private Map map = new HashMap<>();
      ​
          public BeanFactory(){
              // 创建bean注册器
              beanRegister = new BeanRegister();
              // 加载资源
              this.map = new ResourceLoader().getResource();
          }
      ​
          /**
           * 获取bean
           * @param beanName
           * @return
           */
          public Object getBean(String beanName) {
              Object bean = beanRegister.getSingletonBean(beanName);
              if (bean != null) {
                  return bean;
              }
              return createBean(map.get(beanName));
          }
      ​
          /**
           * 创建bean
           * @param beanDefinition
           * @return
           */
          private Object createBean(BeanDefinition beanDefinition) {
              try {
                  Object bean = beanDefinition.getBeanClass().newInstance();
                  beanRegister.registerSingletonBean(beanDefinition.getBeanName(), bean);
                  return bean;
              } catch (InstantiationException e) {
                  e.printStackTrace();
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              }
              return null;
          }
      }
    6. 测试验证。

      public class TestUser {
          @Test
          public void beanFactory() {
              BeanFactory beanFactory = new BeanFactory();
      ​
              // 第一次获取,通过反射
              User user = (User) beanFactory.getBean("user");
              user.sayHello();
      ​
              // 第二次获取,通过缓存
              User user1 = (User) beanFactory.getBean("user");
              user.sayHello();
      ​
              // 所有对象都是单例的前提下,是同一个对象
              System.out.println(user1 == user);
          }
      }
    高级容器ApplicationContext
    • ApplicationContext继承自BeanFactory,拥有更多的功能和特性,包括国际化、事件传播、资源访问等。

    • 和BeanFactory的延迟加载不同,ApplicationContext会在容器启动时就实例化和初始化所有的bean。

    • 支持更丰富的配置方式,包括XML配置、注解、java配置等,并且支持自动扫描并注册bean。

    ApplicationContext通过读取xml配置的形式获取bean:

    public class MySpringApplication {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            Product product = (Product) applicationContext.getBean("product");
            System.out.println(product.getId());
        }
    }
    IoC容器工作过程

    Spring 的 IOC 容器⼯作的过程,其实可以划分为两个阶段:容器启动阶段和Bean实例化阶段。

    Spring AOP

    AOP是Aspect-Oriented Programming(面向方面编程或面向切面)的简称,是一种编程范式,用于增强、扩展和管理应用程序的功能。

    • 通过将交叉关注点(Cross-Cutting Concerns)从应用程序的主要业务逻辑中分离出来,实现了更好的模块化和可维护性。

    • 通常包括日志记录、事务管理、安全性、异常处理等方面的功能。

    简单的Spring AOP示例

    1.项目中添加Spring AOP相关的依赖。

            
                org.springframework.boot
                spring-boot-starter-aop
                5.3.27
            

    2.创建一个目标类(Target Class),这是我们将应用AOP的类。

    public class MyService {
        public void showTime() {
            System.out.println("Now :" + new Date(System.currentTimeMillis()));
        }
    ​
        public void sayHi() {
            System.out.println("Hi");
        }
    }

    3.创建一个切面类(Aspect Class),这是我们的AOP切面。

    @Aspect
    public class LoggerAspect {
        public final static Logger logger = LoggerFactory.getLogger(LoggerAspect.class);
    ​
        /**
         * MyService类作为切点
         */
        @Pointcut("execution(* com.elaine.myspring.aop.service.MyService.*(..))")
        public void myLogger(){}
    ​
    ​
        @Before("myLogger()")
        public void doBefore() {
            logger.info("Before PointCut, say Hello!");
        }
    ​
        @After("myLogger()")
        public void doAfter() {
            logger.info("After PointCut, say Bye!");
        }
    }

    4.配置文件配置AOP

    
    
    
        
        
        
        
        
        
    

    5.调用方法

    public class MySpringApplication {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            MyService service = (MyService) applicationContext.getBean("myService");
            service.showTime();
            service.sayHi();
        }
    }

    结果

  • 相关阅读:
    用半天时间从零开始复习前端之html
    基于Java在线教学质量评价系统设计实现(源码+lw+部署文档+讲解等)
    深入浅出嵌入式虚拟机原理,实现“小而能”嵌入式虚拟机!(文末送书)
    PAT 甲级 A1072 Gas Station
    EVPN-Vxlan隧道跨子网互访实验配置(集中式网关)
    7.提交任务到 NioEventLoop(Nio事件循环执行线程)
    男士证件照要不要西服领带?
    企业如何通过会员积分营销留住客户?
    QT QFile
    VA05/VF05不好用,加N试试
  • 原文地址:https://blog.csdn.net/Elaine2391/article/details/133901455