美文网首页Java入门基础Java 后台开发Spring源码剖析
Spring由Bean出发的使用及相关核心功能

Spring由Bean出发的使用及相关核心功能

作者: 在前行路上的奔跑 | 来源:发表于2020-03-02 02:57 被阅读0次

    一、Spring工程的创建

    1、环境预设

    • Maven
    • JDK1.8
    • Spring5.1.7
    • Idea

    2、项目创建

    1.使用Idea构建一个普通Maven项目

    2.引入Spring5.1.7,详细看下面pom.xml

    <?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>org.wh.spring</groupId>
        <artifactId>spring-vip-ioc</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.1.7.RELEASE</version>
            </dependency>
        </dependencies>
    
    </project>
    

    3、创建Spring配置文件

    在项目resources里创建applicationContext.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        
    </beans>
    

    二、Spring初始化的几种方式

    1.默认为项目工作路径,及项目的根目录

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    

    2.使用前缀file,表示文件的绝对路径

    ApplicationContext context = new ClassPathXmlApplicationContext("file:D:/applicationContext.xml");
    

    3.加载多个配置文件

    String[] xmlCfg = new String[] {"applicationContext.xml", "file:D:/applicationContext.xml"};
    ApplicationContext context = new ClassPathXmlApplicationContext(xmlCfg);
    

    4.通配符加载

    ApplicationContext context = new ClassPathXmlApplicationContext("spring-*.xml");
    

    5.没有前缀:默认为项目的classpath下相对路径

    ApplicationContext context = new FileSystemXmlApplicationContext("/src/main/resources/spring-1.xml");
    

    6.使用前缀file,表示文件的绝对路径

    ApplicationContext context = new FileSystemXmlApplicationContext("file:D:/spring-1.xml");
    

    7.加载多个配置文件

    String[] xmlCfg = new String[] {"file:D:/spring-1.xml", "classpath:spring-2.xml"};
            ApplicationContext context = new FileSystemXmlApplicationContext(xmlCfg);
    

    8.通配符加载

    ApplicationContext context = new FileSystemXmlApplicationContext("classpath:spring-*.xml");
    

    9.注解初始化(完成无xml化)

    创建带有@Configuration的spring配置类,来代替applicationContext.xml

    package org.wh.spring.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.wh.spring.model.User;
    
    @Configuration
    public class SpringApplicationConfig {
    
        @Bean("user2")
        public User getUser() {
            User user = new User();
            user.setName("小明");
            user.setAge(20);
            return user;
        }
    }
    
    

    加载测试

    package org.wh.spring;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.wh.spring.config.SpringApplicationConfig;
    import org.wh.spring.model.User;
    
    /**
     * 主入口
     */
    public class ApplicationContextMain {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringApplicationConfig.class);
            User user = (User) context.getBean("user2");
            System.out.println(user);
            System.out.println(context);
        }
    
    }
    

    10.使用@ImportResource读取配置文件

    package org.wh.spring.config;
    
    import org.springframework.context.annotation.ImportResource;
    
    @ImportResource("spring-1.xml")
    public class SpringApplicationConfig {
    
    }
    

    spring-1.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="order" name="order" class="org.wh.spring.model.Order">
            <property name="orderNumber" value="10011001100"></property>
            <property name="price" value="21.00"></property>
        </bean>
    
    </beans>
    

    测试

    package org.wh.spring;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.wh.spring.config.SpringApplicationConfig;
    import org.wh.spring.model.Order;
    import org.wh.spring.model.User;
    
    /**
     * 主入口
     */
    public class ApplicationContextMain {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringApplicationConfig.class);
            Order order = (Order) context.getBean("order");
            System.out.println(order);
            System.out.println(context);
        }
    
    }
    

    类图预览

    Spring提供的两种容器类型,ApplicationContext和BeanFactory区别

    两者都是用来从容器中获取spring beans的,不同之处在于BeanFactory使用的是懒加载,也就是在我们通过getBean()调用它们时才会进行实例化,而ApplicationContext继承自BeanFactory,与前者不同的在于ApplicationContext在启动时就将所有beans全部实例化了

    如何选择使用

    因为BeanFactory是懒加载的,在调用时才能实例化,所以对内存消耗比较小,适合对资源有限情况

    而ApplicationContext,在ApplicationContext启动时将所有的Bean都加载了,不需要每次调用在实例化使得应用运行速度较之更快

    当然,在实际开发应用中ApplicationContext更为常用

    三、基于XML的bean初始化及应用

    1.Bean属性标签

    • id

      bean的id,需满足XML命名规范

    • name

      bean的name,与id一样,它们都是唯一性的,在配置文件中不允许出现两个

    • class

      指向要初始化的类

    • property

      属性赋值

    • ref

      引用对象

    • constructor-arg

      构造函数,例:<constructor-arg index="1" type="float" value="20.00" />

      • index 构造函数中第几个参数

      • type 数据类型,基础数据类型直接写,否则写全路径java.lang.String

      • value 赋值

    2.Bean功能标签

    • init-method

      初始化时调用的方法

    • destroy-method

      销毁时调用的方法

    • Scope

      对象在spring容器(IoC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式

      • singleton 单例模式
      • prototype 原型模式

    3.示例演示

    User

    package org.wh.spring.model;
    
    public class User {
        private String name;
        private int age;
        private Order order;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Order getOrder() {
            return order;
        }
    
        public void setOrder(Order order) {
            this.order = order;
        }
    
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", order=" + order +
                    '}';
        }
    
    
        public void initMethod() {
            System.out.println("-----------User类初始化方法--------------");
        }
    
        public void destroyMethod() {
            System.out.println("-----------User类销毁方法--------------");
        }
    
    
    }
    
    

    Order

    package org.wh.spring.model;
    
    public class Order {
        private String orderNumber;
        private float price;
    
        public Order(String orderNumber, float price) {
            this.orderNumber = orderNumber;
            this.price = price;
        }
    
        public String getOrderNumber() {
            return orderNumber;
        }
    
        public void setOrderNumber(String orderNumber) {
            this.orderNumber = orderNumber;
        }
    
        public float getPrice() {
            return price;
        }
    
        public void setPrice(float price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Order{" +
                    "orderNumber='" + orderNumber + '\'' +
                    ", price=" + price +
                    '}';
        }
    
    }
    
    

    applicationContext.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- 用户 -->
        <bean id="user" name="user" class="org.wh.spring.model.User" init-method="initMethod" destroy-method="destroyMethod" scope="prototype">
            <property name="name" value="小明"></property>
            <property name="age" value="6"></property>
            <property name="order" ref="order"></property>
        </bean>
    
        <!-- 订单 -->
        <bean id="order" name="order" class="org.wh.spring.model.Order">
            <constructor-arg index="0" type="java.lang.String" value="100110001110" />
            <constructor-arg index="1" type="float" value="20.00" />
        </bean>
    
    </beans>
    

    主入口,运行测试

    ApplicationContextMain

    package org.wh.spring;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.wh.spring.model.User;
    
    /**
     * 主入口
     */
    public class ApplicationContextMain {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            User user = (User) context.getBean("user");
            System.out.println(user);
            ((ClassPathXmlApplicationContext)context).close();
    
        }
    
    }
    

    四、基于注解的bean初始化及应用

    1.声明Bean注解:

    • @ Bean

      指定为spring的bean

    • @Component

      指定为组件,但无具体角色

    • @Controller

      注册为控制器

    • @Service

      注册为service,逻辑处理层对象

    • Repository

      注册数据访问层对象

    2.注入Bean注解

    JSR是Java Specification Requests的缩写,意思是Java规范提案

    • @Autowired

      由Spring提供

    • @Inject

      由JSR-330提供

    • @Resource

      由JSR-250提供

    • @PostConstruct

      由JSR-250提供,在构造函数执行完之后执行,等价于xml配置中的bean的initMethod

    • @PreDestory

      由JSR-250提供,在Bean销毁之前执行,等价于xml配置文件的bean的destroyMethod

    3.配置类相关注解

    • @Configuration

      声明当前类为配置类,相当于xml形式的Spring配置(类上)

    • @Bean

      注解在方法上,声明当前方法的返回值为一个bean,替代xm中的方式(方法上)

    • @Value

      为属性注入值(支持普通字符、系统属性、表达式结果、其他bean属性等)

    • @ComponentScan

      用于对Component进行扫描,相当于xml中的(类上)

    • @WishlyConfiguration

      为@Configuration与@ComponentScan的组合注解,可以替代这两个注解

    3.示例演示

    预览一下结构


    User

    package org.wh.spring.model;
    
    public class User {
        private String name;
        private int age;
        private Order order;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Order getOrder() {
            return order;
        }
    
        public void setOrder(Order order) {
            this.order = order;
        }
    
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", order=" + order +
                    '}';
        }
    
    
        public void initMethod() {
            System.out.println("-----------User类初始化方法--------------");
        }
    
        public void destroyMethod() {
            System.out.println("-----------User类销毁方法--------------");
        }
    
    
    }
    
    

    Order

    package org.wh.spring.model;
    
    public class Order {
        private String orderNumber;
        private float price;
    
        public Order(String orderNumber, float price) {
            this.orderNumber = orderNumber;
            this.price = price;
        }
    
        public String getOrderNumber() {
            return orderNumber;
        }
    
        public void setOrderNumber(String orderNumber) {
            this.orderNumber = orderNumber;
        }
    
        public float getPrice() {
            return price;
        }
    
        public void setPrice(float price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Order{" +
                    "orderNumber='" + orderNumber + '\'' +
                    ", price=" + price +
                    '}';
        }
    
    }
    
    

    Product

    package org.wh.spring.model;
    
    import org.springframework.beans.factory.annotation.Value;
    
    public class Product {
        @Value("一本小黄书")
        private String productName;
    
        public String getProductName() {
            return productName;
        }
    
        public void setProductName(String productName) {
            this.productName = productName;
        }
    
        @Override
        public String toString() {
            return "Product{" +
                    "productName='" + productName + '\'' +
                    '}';
        }
    }
    
    

    SpringApplicationConfig

    package org.wh.spring.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.wh.spring.model.Product;
    
    @Configuration
    public class SpringApplicationConfig {
    
        @Bean("product")
        public Product getProduct() {
            return new Product();
        }
    
    }
    
    

    UserService

    package org.wh.spring.service;
    
    import org.wh.spring.model.User;
    
    public interface UserService {
        User getUserInfo();
    }
    
    

    UserServiceImpl

    package org.wh.spring.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.wh.spring.model.User;
    import org.wh.spring.service.UserService;
    
    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private User user;
    
        @Override
        public User getUserInfo() {
            return user;
        }
    }
    
    

    UserController

    package org.wh.spring.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.wh.spring.model.User;
    import org.wh.spring.service.impl.UserServiceImpl;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    @Controller
    public class UserController {
    
        @Autowired
        private UserServiceImpl userService;
    
        public User getUser() {
            return userService.getUserInfo();
        }
    
        @PostConstruct
        public void initMethod() {
            System.out.println("-----------UserController类初始化方法--------------");
        }
    
        @PreDestroy
        public void destroyMethod() {
            System.out.println("----------UserController类销毁方法--------------");
        }
    
    
    }
    
    

    applicationContext.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
            https://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="user" name="user" class="org.wh.spring.model.User" init-method="initMethod" destroy-method="destroyMethod" scope="singleton">
            <property name="name" value="小明"></property>
            <property name="age" value="6"></property>
            <property name="order" ref="order"></property>
        </bean>
    
        <!-- 订单 -->
        <bean id="order" name="order" class="org.wh.spring.model.Order">
            <constructor-arg index="0" type="java.lang.String" value="100110001110" />
            <constructor-arg index="1" type="float" value="20.00" />
        </bean>
    
        <context:component-scan base-package="org.wh.spring" ></context:component-scan>
    
    </beans>
    

    运行测试

    package org.wh.spring;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.wh.spring.controller.UserController;
    import org.wh.spring.model.Product;
    import org.wh.spring.model.User;
    
    /**
     * 主入口
     */
    public class ApplicationContextMain {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            // 获取UserController
            UserController userController = context.getBean(UserController.class);
            User user = userController.getUser();
    
            System.out.println(user);
    
            // @Value
            Product product = context.getBean(Product.class);
    
            System.out.println(product);
    
            // 关闭
            ((ClassPathXmlApplicationContext)context).close();
    
        }
    
    }
    
    

    运行结果

    -----------User类初始化方法--------------
    -----------UserController类初始化方法--------------
    User{name='小明', age=6, order=Order{orderNumber='100110001110', price=20.0}}
    Product{productName='一本小黄书'}
    ----------UserController类销毁方法--------------
    -----------User类销毁方法--------------
    

    \color{green}{学习推荐:}https://ke.qq.com/course/434219

    或者加群进行讨论:857565362,并获取学习资源

    相关文章

      网友评论

        本文标题:Spring由Bean出发的使用及相关核心功能

        本文链接:https://www.haomeiwen.com/subject/goxskhtx.html