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

目录

Spring IoC

IoC的设计与实现

简单容器BeanFactory

高级容器ApplicationContext

IoC容器工作过程

Spring AOP

简单的Spring AOP示例


聊聊分布式架构07-[Spring]IoC和AOP_第1张图片

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实例化阶段。

聊聊分布式架构07-[Spring]IoC和AOP_第2张图片

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();
    }
}

结果

你可能感兴趣的:(分布式架构,分布式,架构,spring)