【Java】Spring5学习

基础环境与文档资料:

见黑马视频:

https://www.bilibili.com/video/BV1P44y1N7QG

依赖坐标:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.cloud9</groupId>
    <artifactId>Spring5</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
    </dependencies>
</project>

  

一、ApplicationContext接口

package cn.cloud9;

import cn.cloud9.bean.Component1;
import cn.cloud9.event.UserRegisteredEvent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;

/**
 * @projectName: Spring5
 * @author: OnCloud9
 * @date: 2023年02月07日 09:13
 * @version: 1.0
 */
@Slf4j
@SpringBootApplication
public class MainApplication {

    @SneakyThrows
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(MainApplication.class, args);
        log.info("ConfigurableApplicationContext -> {}", applicationContext);

        /*
         * ApplicationContext的功能
         * 1、I18N支持, MessageSource接口实现
         *  - 默认读取的配置文件:messages.properties
         *  - 指定文件文件名称 中文zh 英文en 日文ja
         */
        String cnHello = applicationContext.getMessage("hello", null, Locale.CHINA);
        String enHello = applicationContext.getMessage("hello", null, Locale.ENGLISH);
        String jpHello = applicationContext.getMessage("hello", null, Locale.JAPANESE);
        log.info("I18N 国际化参数读取 CN -> {}, EN -> {}, JP -> {}", cnHello, enHello, jpHello);

        /*
         * ApplicationContext的功能
         * 2、读取类路径下的资源
         *  - classpath: * 读取当前项目下的类路径资源
         *  - classpath*: * 读取项目所有依赖下的类路径
         */
        Resource[] resources = applicationContext.getResources("classpath:*");
        Arrays.stream(resources).forEach(resource -> log.info("classpath: -> {}", resource));

        resources = applicationContext.getResources("classpath*:*");
        Arrays.stream(resources).forEach(resource -> log.info("classpath*: -> {}", resource));

        // 获取Spring的SPI配置文件
        resources = applicationContext.getResources("classpath*:META-INF/spring.factories");
        Arrays.stream(resources).forEach(resource -> log.info("META-INF/spring.factories: -> {}", resource));

        /*
         * ApplicationContext的功能
         * 3、读取配置文件的值
         */
        ConfigurableEnvironment environment = applicationContext.getEnvironment(); // 系统变量 + 配置文件
        String javaHome = environment.getProperty("java_home");
        String serverPort = environment.getProperty("server.port");
        log.info("javaHome -> {}, serverPort -> {}", javaHome, serverPort);

        /*
         * ApplicationContext的功能
         * 4、发布事件
         *  - 发布事件的意义是为了解耦业务逻辑
         */

        // 1、使用ApplicationContext直接发布事件
        UserRegisteredEvent userRegisteredEvent = new UserRegisteredEvent(applicationContext);
        applicationContext.publishEvent(userRegisteredEvent);

        // 2、使用Bean对象发布事件
        Component1 component1 = applicationContext.getBean("component1", Component1.class);
        component1.registerBusinessAction();
    }
}

I18N国际化配置文件:

 

  

 

UserRegisteredEvent事件源类:

package cn.cloud9.event;

import org.springframework.context.ApplicationEvent;

/**
 * 用户注册事件类
 * @author OnCloud9
 * @version 1.0
 * @project Spring5
 * @date 2023年02月08日 10:45
 */
public class UserRegisteredEvent extends ApplicationEvent {
    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public UserRegisteredEvent(Object source) {
        super(source);
    }
}

 

在Component2类的监听方法:

package cn.cloud9.bean;

import cn.cloud9.event.UserRegisteredEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * @projectName: Spring5
 * @author: OnCloud9
 * @date: 2023年02月07日 09:30
 * @version: 1.0
 */
@Slf4j
@Component
public class Component2 {


    /**
     * @author OnCloud9
     * @date 2023/2/8 11:01
     * @description
     * @params [event]
     * @return void
     */
    @EventListener
    public void receiveEvent(UserRegisteredEvent event) {
        log.info("用户注册事件触发, 监听方法执行!!!!");
    }
}

  

Component1中的发布事件方法:

package cn.cloud9.bean;

import cn.cloud9.event.UserRegisteredEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @projectName: Spring5
 * @author: OnCloud9
 * @date: 2023年02月07日 09:30
 * @version: 1.0
 */
@Slf4j
@Component
public class Component1 {

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;


    /**
     * @author OnCloud9
     * @date 2023/2/8 11:06
     * @description 用户注册业务行为
     * @params []
     * @return void
     */
    public void registerBusinessAction() {
        log.info("用户注册业务行为开始!");
        applicationEventPublisher.publishEvent(new UserRegisteredEvent(this));
    }
}

  

启动时打印信息:

2023-02-08 14:36:50.523  INFO 6548 --- [           main] cn.cloud9.bean.Component2                : 用户注册事件触发, 监听方法执行!!!!
2023-02-08 14:36:50.524  INFO 6548 --- [           main] cn.cloud9.bean.Component1                : 用户注册业务行为开始!
2023-02-08 14:36:50.524  INFO 6548 --- [           main] cn.cloud9.bean.Component2                : 用户注册事件触发, 监听方法执行!!!!

 

二、BeanFactory接口

/*
 * BeanFactory
 * 1、是ApplicationContext的父接口
 * 2、是Spring的核心容器
 * 3、ApplicationContext组合了BeanFactory的功能
 * 4、获取Bean对象,控制反转,依赖注入,Bean的生命周期的各种功能,由BeanFactory的实现类完成
 */
Field field = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
field.setAccessible(true);
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
Map<String,Object> beanTanker = (Map<String,Object>)field.get(beanFactory);
beanTanker.entrySet().stream().filter(e -> e.getKey().startsWith("component")).forEach(e -> {
  log.info("key -> {}, value -> {}", e.getKey(), e.getValue());
});

  

import cn.cloud9.MainApplication;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @author OnCloud9
 * @version 1.0
 * @project Spring5
 * @date 2023年02月08日 11:12
 */
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BeanFactoryTest {

    /**
     * @author OnCloud9
     * @date 2023/2/8 13:47
     * BeanFactory
     *  - 不会主动调用BeanFactory的后置处理器
     *  - 不会主动调用Bean的后置处理器
     *  - 不会主动初始化单例Bean对象
     *  - 不会解析BeanFactory, 包括${} #{} 值注入
     *  Bean的后处理有排序逻辑
     *
     */
    @Test
    public void beanInitializeProcess() {
        /*
         *  Bean的定义, 初始化, scope, 销毁,
         */
        final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        /* 1、生成Bean的定义对象 */
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();

        /* 2、Bean工厂注册定义对象 */
        beanFactory.registerBeanDefinition("config", beanDefinition);

        /* 3、获取注册的Bean定义名称集合 */
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) log.info("beanDefinitionName: {}", beanDefinitionName);
    }

    @Configuration
    static class Config {

        @org.springframework.context.annotation.Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @org.springframework.context.annotation.Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }

    @Data
    private static class Bean1 {
        @Autowired
        private Bean2 bean2;
    }

    private static class Bean2 {}

}

  

在注册Bean定义对象之后

beanFactory.registerBeanDefinition("config", beanDefinition);

BeanFactory对象中只有当前这个config的Bean定义对象

一些自动装配注解,事件监听需要后置处理器的加入:

/* 4、添加一些常用的后处理器 */
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
/*
 * org.springframework.context.annotation.internalConfigurationAnnotationProcessor
 * org.springframework.context.annotation.internalAutowiredAnnotationProcessor
 * org.springframework.context.annotation.internalCommonAnnotationProcessor
 * org.springframework.context.event.internalEventListenerProcessor
 * org.springframework.context.event.internalEventListenerFactory
 */
log.info("添加后置处理器后...");
beanDefinitionNames = beanFactory.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) log.info("beanDefinitionName : {}", beanDefinitionName);

打印结果:

2023-02-08 14:54:26.964  INFO 33432 --- [           main] BeanFactoryTest                          : 添加后置处理器后...
2023-02-08 14:54:26.964  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: config
2023-02-08 14:54:26.965  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
2023-02-08 14:54:26.965  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
2023-02-08 14:54:26.965  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.annotation.internalCommonAnnotationProcessor
2023-02-08 14:54:26.965  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.event.internalEventListenerProcessor
2023-02-08 14:54:26.965  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.event.internalEventListenerFactory

  

但是我们发现Bean1和Bean2并没有在BeanFactory中注册

BeanFactory的后置处理器只是被添加到BeanFactory,并没有调用处理方法

所以需要把每个处理器的处理方法都调用一遍才行

/* 5、获取BeanFactory处理器的容器, 用于BeanFactory的后置处理器的添加 */
Map<String, BeanFactoryPostProcessor> processorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
processorMap.values().forEach(p -> {
  /* 调用每个处理器的处理方法, 扩充Bean的定义 */
  p.postProcessBeanFactory(beanFactory);
});

log.info("在后置处理器处理后..."); /* config下的 bean1 bean2 被注册进来 */
beanDefinitionNames = beanFactory.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) log.info("beanDefinitionName: {}", beanDefinitionName);

再次打印之后发现,Bean1和Bean2加入进来了:

2023-02-08 14:54:26.972  INFO 33432 --- [           main] BeanFactoryTest                          : 在后置处理器处理后...
2023-02-08 14:54:26.972  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: config
2023-02-08 14:54:26.972  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
2023-02-08 14:54:26.972  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
2023-02-08 14:54:26.972  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.annotation.internalCommonAnnotationProcessor
2023-02-08 14:54:26.972  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.event.internalEventListenerProcessor
2023-02-08 14:54:26.972  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: org.springframework.context.event.internalEventListenerFactory
2023-02-08 14:54:26.973  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: bean1
2023-02-08 14:54:26.973  INFO 33432 --- [           main] BeanFactoryTest                          : beanDefinitionName: bean2

  

在Bean1中我们设置了Bean2成员属性,并且标注自动装配

然后在BeanFactory获取Bean1内的Bean2实例时,发现Bean2对象并没有注入:

/* 在没有扫描@Autowired注解驱动时不能装填Bean实例 */
log.info("打印bean2对象:{}", beanFactory.getBean(Bean1.class).getBean2());

打印结果:

2023-02-08 15:09:38.299  INFO 3852 --- [           main] BeanFactoryTest                          : 打印bean2对象:null

 

因为之前的处理只针对BeanFactory的后置处理,对于一个配置Bean来说

配置Bean中要注册的Bean并不归于BeanFactory的后置处理,而是Bean的后置处理

所以这里需要做Bean的后置处理:

/* 添加Bean的后置处理器 */
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);

/* 在Bean的处理器添加之后,Bean2的对象装配了 */
log.info("打印bean2对象:{}", beanFactory.getBean(Bean1.class).getBean2());

打印结果:

2023-02-08 15:15:54.219  INFO 23160 --- [           main] BeanFactoryTest                          : 打印bean2对象:BeanFactoryTest$Bean2@2c6aed22

  

Bean不会被BeanFactory主动初始化,在首次获取这个Bean时初始化

如果需要的情况,可以调用预先实例化方法,提前创建

/* Bean对象一般在调用getBean获取时才创建, 也可以调用预先实例化方法提前创建 (只针对scope为单例的对象) */
beanFactory.preInstantiateSingletons();

  

 2、自动装配的执行顺序

新增一个InterFaceType接口,Bean3和Bean4同时实现这个接口

在Bean1注册这个接口,Spring如何装配这个成员属性?

    @Data
    private static class Bean1 {
        @Autowired
        private Bean2 bean2;

        // 1、指定声明bean名称
        // @Autowired @Qualifier("bean4")
        // private InterFaceType interFaceType;

        // 2、或者变量名称也可以匹配bean名称
        // @Autowired
        // private InterFaceType bean4;

        // 3、使用@Resource声明了名称,则优先级高于变量名称
        // @Resource(name = "bean3")
        // private InterFaceType bean4;

        // 4、又加 @Autowired 又加 @Resource, 交给后处理器的顺序决定先由哪个注解解析器处理
        @Autowired @Qualifier("bean4")
        @Resource(name = "bean3")
        private InterFaceType interFaceType;
    }
    private static class Bean2 {}

    private interface InterFaceType {}
    private static class Bean3 implements InterFaceType {}
    private static class Bean4 implements InterFaceType {}

  

我们打印这个接口类型看看:

/*
 * 可以看到默认是自动装配注解处理器先执行,所以bean4先被装填
 * org.springframework.context.annotation.internalAutowiredAnnotationProcessor
 * org.springframework.context.annotation.internalCommonAnnotationProcessor
 */
log.info("InterFaceType Spring实际装填对象 -> {}",  beanFactory.getBean(Bean1.class).getInterFaceType());

 打印结果:

2023-02-08 15:22:30.444  INFO 23516 --- [           main] BeanFactoryTest                          : InterFaceType Spring实际装填对象 -> BeanFactoryTest$Bean4@3c46dcbe

  

若要改变注解的处理顺序,就改变Bean后置处理器类的处理顺序:

/* 更改后置处理器的添加顺序 将@Resource优先被添加执行 @Autowired滞后 */
beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
 .sorted(beanFactory.getDependencyComparator())
 .forEach(beanFactory::addBeanPostProcessor);

/*
 * 默认是自动装配注解处理器先执行
 * org.springframework.context.annotation.internalAutowiredAnnotationProcessor
 * org.springframework.context.annotation.internalCommonAnnotationProcessor
 */
log.info("InterFaceType Spring实际装填对象 -> {}",  beanFactory.getBean(Bean1.class).getInterFaceType());

打印结果:

2023-02-08 15:29:52.865  INFO 32756 --- [           main] BeanFactoryTest                          : InterFaceType Spring实际装填对象 -> BeanFactoryTest$Bean3@3c46dcbe

  

3、排序比较器对象

基于这个对象来决定处理器的先后顺序

beanFactory.getDependencyComparator()

 

 在一开始的BeanFactory注册中就已经放置了

 

比较器基于处理器的顺序属性决定先后:

 

 

这里在源码可以看到两个顺序值: 

 

 

我们写个测试类比较便知:

@Test
public void processorOrderCompare() {
    int orderForResource = Ordered.LOWEST_PRECEDENCE - 3;
    int orderForAutowired = 2147483645;
    log.info("@Resource -> {}, @Autowired -> {}", orderForResource, orderForAutowired);
    log.info("@Resource > @Autowired ? {}", orderForResource > orderForAutowired);
}

打印结果:

2023-02-08 15:57:31.929  INFO 17840 --- [           main] BeanFactoryTest                          : @Resource -> 2147483644, @Autowired -> 2147483645
2023-02-08 15:57:31.931  INFO 17840 --- [           main] BeanFactoryTest                          : @Resource > @Autowired ? false

  

三、ApplicationContextImpl的实现  

4种上下文的实现方式配置:

package cn.cloud9.spring;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.Controller;

import java.net.URL;

@Slf4j
public class ApplicationContextImpl {

    public static void main(String[] args) {
        classpathXmlApplicationContext();
        systemXmlApplicationContext();
        annotationConfigApplicationContext();
        webServletApplicationContext();
    }

    /**
     * @author OnCloud9
     * @date 2023/2/8 16:30
     * @description xml方式配置bean
     * @params []
     * @return void
     */
    private static void classpathXmlApplicationContext() {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("context1.xml");
        for (String beanDefinitionName : classPathXmlApplicationContext.getBeanDefinitionNames()) {
            log.info("xmlRegisteredBean: {}", beanDefinitionName);
        }
        log.info("inside bean2 is {}", classPathXmlApplicationContext.getBean(Bean1.class).getBean2());
    }

    /**
     * @author OnCloud9
     * @date 2023/2/8 16:35
     * @description 文件系统方式读取xml配置bean
     * @params []
     * @return void
     */
    private static void systemXmlApplicationContext() {
        URL resource = ApplicationContextImpl.class.getClassLoader().getResource("context1.xml");
        String path = resource.getPath();
        FileSystemXmlApplicationContext fsXmlApplicationContext = new FileSystemXmlApplicationContext(path);
        for (String beanDefinitionName : fsXmlApplicationContext.getBeanDefinitionNames()) {
            log.info("systemXmlRegisteredBean: {}", beanDefinitionName);
        }
        log.info("inside bean2 is {}", fsXmlApplicationContext.getBean(Bean1.class).getBean2());
    }

    /**
     * @author OnCloud9
     * @date 2023/2/8 16:35
     * @description 当前配置类方式实现Bean配置
     * @params []
     * @return void
     */
    private static void annotationConfigApplicationContext() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfigurationClass.class);
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            log.info("javaAnnotationBean: {}", beanDefinitionName);
        }
        log.info("inside bean2 is {}", applicationContext.getBean(Bean1.class).getBean2());
    }
    
    /**
     * @author OnCloud9 
     * @date 2023/2/9 09:10
     * @description WebServlet应用上下文对象Bean配置
     * @params []
     * @return void
     */
    private static void webServletApplicationContext() {
        AnnotationConfigServletWebServerApplicationContext applicationContext =
                new AnnotationConfigServletWebServerApplicationContext(WebMvcConfig.class);
    }

    @Data
    static class Bean1 {
        private Bean2 bean2;
    }
    static class Bean2 {}

    @Configuration
    static class BeanConfigurationClass {
        @Bean
        public Bean1 bean1(Bean2 bean2) {
            Bean1 bean1 = new Bean1();
            bean1.setBean2(bean2);
            return bean1;
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }

    @Configuration
    static class WebMvcConfig {
        /* ServletWeb服务器工厂对象配置,默认按Tomcat实现 */
        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            return new TomcatServletWebServerFactory();
        }

        /* 配置前置请求分发处理器 */
        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        /* 分发注册Bean */
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        /* 直接注册一个控制器 */
        @Bean("/controller1")
        public Controller controller() {
            return (request, response) -> {
                response.getWriter().write("这是配置类的Controller!");
                return null;
            };
        }
    }
}

 

XML方式的配置文件(context1.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="bean1" class="cn.cloud9.spring.ApplicationContextImpl.Bean1" >
        <property name="bean2" ref="bean2" />
    </bean>
    <bean id="bean2" class="cn.cloud9.spring.ApplicationContextImpl.Bean2" />

    <!--
        后处理器的注册
        org.springframework.context.annotation.internalConfigurationAnnotationProcessor
        org.springframework.context.annotation.internalAutowiredAnnotationProcessor
        org.springframework.context.annotation.internalCommonAnnotationProcessor
        org.springframework.context.event.internalEventListenerProcessor
        org.springframework.context.event.internalEventListenerFactory
    -->
    <context:annotation-config />
</beans>

  

 

 

 

 

 

  

 

posted @ 2023-02-08 17:13  emdzz  阅读(14)  评论(0编辑  收藏  举报