spring框架-1-Bean

spring框架介绍

spring是什么

Spring是一个 IOC(DI) 和 AOP 容器框架

spring分为哪些模块,整体架构

在这里插入图片描述

spring怎样导入到项目

1. maven方式

spring的核心依赖(core beans expression context)

	<!-- spring 5.2.0 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>5.2.0.RELEASE</version>
    </dependency>
2. 下载jar包,在导入项目

自己在网上下载jar包引入项目了,我不在此提供jar包的下载地址

通过xml文件配置bean

1. 声明一个简单的bean

在Spring配置文件中写一个bean标签就可以了

<bean id="stu" class="online.abor.domain.Student"/>

class:指定这个bean是什么类型的bean,就是简单来说就是类的路径
id:就像是数据库中一个表的主键一样,在这里是bean的唯一标识

2. 配置bean的属性
  • 配置bean的基本值
    需要用到bean的子标签property来配置

    	<bean id="car" class="online.abor.domain.Car">
            <property name="brand" value="BMW"/>
            <property name="maxSpeed" value="240"/>
            <property name="price" value="540000"/>
        </bean>
    
  • 配置引用类型的值

  1. 需要用property的属性ref来使其指向其他的bean

    	<bean id="stuCar" class="online.abor.domain.Student">
            <property name="name" value="carStu"/>
            <property name="car" ref="car"/>
        </bean>
    
  2. 使用内部bean来配置
    这个内部bean是不需要id字段的,因为其他的bean根本就访问不到这个内部bean

    	<bean id="stuInnerCar" class="online.abor.domain.Student">
           <property name="name" value="stuInnerCar"/>
            <property name="car">
                <bean class="online.abor.domain.Car">
                    <property name="brand" value="BenChi"/>
                    <property name="maxSpeed" value="280"/>
                    <property name="price" value="340000"/>
                </bean>
            </property>
        </bean>
    
  3. 级联属性
    通过 . 的方式设置引用类型的值

    	<bean id="cascadeStu" class="online.abor.domain.Student">
            <property name="name" value="cascadeStu"/>
            <property name="car" ref="car"/>
            <property name="car.brand" value="SanYi"/>
        </bean>
    

==注意:==如果不先实例化一个car的直接使用级联属性是会报NullValueInNestedPathException异常的,原因是bean在初始化时,并不会为引用类型的字段自动实例化

  • 配置List类的列表
    通过property 的子标签list配置需要的列表
    list下可以直接写bean,也可以使用引用标签ref引用其他的bean
    	<bean id="carsStu" class="online.abor.domain.Student">
            <property name="name" value="carsStu"/>
            <property name="cars">
                <list>
                    <ref bean="car"/>
                    <bean class="online.abor.domain.Car">
                        <property name="brand" value="BenChi"/>
    	                <property name="maxSpeed" value="280"/>
    	                <property name="price" value="340000"/>
                    </bean>
                </list>
            </property>
        </bean>
    
  • 配置Map
    通过property 下的map子标签实现
    map中的每一个键值对对应一个entry子标签
    	<bean id="mapStu" class="online.abor.domain.Student">
            <property name="name" value="mapStu"/>
            <property name="parents">
                <map>
                    <entry key="Father" value="50"/>
                    <entry key="Mother" value="48"/>
                </map>
            </property>
        </bean>
    
  • 配置Properties引用类型值
    通过property 的子标签props设置,每一个prop子标签都是一个属性
    	<bean id="propStu" class="online.abor.domain.Student">
            <property name="name" value="propStu"/>
            <property name="dataSource">
                <props>
                    <prop key="username">root</prop>
                    <prop key="password">123456</prop>
                    <prop key="url">jdbc:mysql://localhost:3306:mysql</prop>
                    <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
                </props>
            </property>
        </bean>
    
  • 通过p标签简化配置bean的属性
    不需要再写property 标签,直接用 p:属性名 给属性赋值
        <bean id="pStu" class="online.abor.domain.Student" p:name="pStu" p:cars-ref="carList"/>
    
  • 列表抽离出来供所有bean公共使用
    列表不需要写class属性,但必须写id属性,否则其他bean不知道如何引用此列表
    	<util:list id="carList">
            <ref bean="car"/>
            <bean class="online.abor.domain.Car">
                <constructor-arg value="LingMu"/>
                <constructor-arg value="180000.23"/>
                <constructor-arg value="100"/>
            </bean>
        </util:list>
    

通过外部属性文件配置bean

一般对于一些项目的配置文件,写在bean配置文件里是很不方便后期更改的,所以一般我们会写在外部属性文件里面,如jdbc.properties文件记录数据库连接的一些信息

  1. 需要先将外部文件导入进来
    在spring配置文件中引入
       <context:property-placeholder location="jdbc.properties"/>
    
  2. 在使用 ${ 属性名 } 引用外部文件中的属性来配置bean
    需要先将配置文件引入进来
    	<context:property-placeholder location="classpath:jdbc.properties"/>
    
    在使用 ${ 属性名 } 引用属性
    	<bean id="alibabaDSP" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="username" value="${user}"/>
            <property name="password" value="${password}"/>
            <property name="url" value="${url}"/>
            <property name="driverClassName" value="${driverClass}"/>
        </bean>
    

spEL表达式

字面量
	<bean id="stu01" class="online.abor.domain.Student">
        <!-- 使用单引号或者双引号界定字符串 -->
        <property name="name" value="#{'spELName'}"/>
        <!-- 整数的字面量 -->
        <property name="age" value="#{18}"/>
        <property name="car">
            <bean class="online.abor.domain.Car">
                <!-- 小数的字面量 -->
                <property name="price" value="#{240000.85}"/>
            </bean>
        </property>
        <!-- 布尔值 -->
        <property name="status" value="#{true }"/>
    </bean>
引用Bean、属性和方法
	<bean id="stu02" class="online.abor.domain.Student">
        <property name="name" value="othersStu"/>
        <!-- 引用其他bean的字段 -->
        <property name="status" value="#{stu01.status}"/>
        <property name="car" value="#{stu01.car}"/>
        <!-- 调用其他类的方法 -->
        <property name="relatives">
            <map>
                <entry key="str" value="#{stu01.toString()}"/>
                <!-- 方法级联链式操作 -->
                <entry key="str2" value="#{stu01.toString().toUpperCase()}"/>
            </map>
        </property>
    </bean>
运算符号
	<!-- 运算符号 -->
    <bean id="stu03" class="online.abor.domain.Student">
        <property name="name" value="operatorStu"/>
        <!-- 逻辑运算符号支持 and or ! not -->
        <property name="status" value="#{stu01.status and true or false and !false}"/>
        <!-- if else  -->
        <property name="age" value="#{stu01.status==true?18:20}"/>
        <!-- 正则表达式 -->
        <property name="sex" value="#{'operatorStu' matches '[0-9]'?'':''}"/>

    </bean>
引用静态类的属性或方法
	<bean id="stu04" class="online.abor.domain.Student">
        <property name="age" value="#{T(Integer).MAX_VALUE}"/>
    </bean>

bean之间的关系

继承

bean 使用parent属性指定需要继承的父bean

    <bean id="autoWireStu"  class="online.abor.domain.Student">
        <property name="name" value="autoWireStu"/>
        <property name="sex" value=""/>
    </bean>

    <!-- 继承 -->
    <bean id="extendsStu" class="online.abor.domain.Student" parent="autoWireStu">
        <property name="name" value="extendsStu"/>
    </bean>

继承可以继承父bean的属性

依赖

bean使用depends-on属性指定需要依赖的bean
如果IOC容器中不存在此bean,会报异常NoSuchBeanDefinitionException

	<!-- 依赖 IOC容器内必须有这个实例,才可以通过IOC的初始化-->
    <bean id="dependCar" class="online.abor.domain.Car" parent="car"/>
    <bean id="dependStu" class="online.abor.domain.Student" depends-on="dependCar">
        <property name="name" value="dependStu"/>
    </bean>
抽象bean

bean使用abstract属性来指定,不可以被实例化
如果这个bean被错误的实例化引用,会报BeanIsAbstractException异常

	<!-- 抽象bean 不可实例化-->
    <bean id="abstractStu" class="online.abor.domain.Student"
          p:name="abName" p:age="18" p:sex="" abstract="true"/>
    <bean id="exAbsStu" parent="abstractStu" class="online.abor.domain.Student">
        <property name="name" value="exAbsStu"/>
    </bean>

bean的生命周期

init与destroy方法

指定bean的init-methoddestroy-method属性

  1. 先在Student类中定义init和destroy方法,方法名是任意的

    	public void init(){
            System.out.println("Student's init-method()");
        }
        public void destroy(){
            System.out.println("Student's destroy-method()");
        }
    
  2. 在配置文件中注入属性

    	<bean id="stu01" class="online.abor.domain.Student"
          init-method="init" destroy-method="destroy"
          p:name="initDestroyStu"/>
    
bean的后置处理器PostProcessor
  1. 自定义一个类实现BeanPostProcessor接口,重写postProcessBeforeInitializationpostProcessAfterInitialization方法

    	public class MyPostProcessor implements BeanPostProcessor {
    	    @Override
    	    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    	        System.out.println("postProcessBeforeInitialization...");
    	        return bean;
    	    }
    	
    	    @Override
    	    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    	        System.out.println("postProcessAfterInitialization...");
    	        return bean;
    	    }
    	}
    
  2. 在配置文件中注入自定义的PostProcessor就可以了就可以了
    不需要赋id属性,只需要class属性,IOC容器会自动识别为后置处理器

    	<bean class="online.abor.others.MyPostProcessor"/>
    

bean的生命周期的执行顺序

  1. 构造器
  2. setter
  3. postProcessBeforeInitialization
  4. 初始化方法 init-method
  5. postProcessAfterInitialization
  6. 销毁方法 destroy-method

通过工厂方法配置bean

静态工厂方法
	<bean id="dateFormat" class="java.text.DateFormat" factory-method="getDateInstance">
		<!-- 可以通过 constructor-arg 子节点为静态工厂方法指定参数 -->
		<constructor-arg value="2"></constructor-arg>
	</bean>
实例工厂方法
	<!-- 实例工厂方法 -->
    <!-- 先创建工厂对象 -->
    <bean id="simpleDateFormat" class="java.text.SimpleDateFormat">
        <constructor-arg value="yyyy-MM-dd hh:mm:ss"/>
    </bean>
    <!-- 在调用非静态方法返回实例 -->
    <bean id="dateTime" factory-bean="simpleDateFormat" factory-method="parse">
        <constructor-arg value="2019-12-1 12:18:20"/>
    </bean>
自定义实例工厂方法返回自定义类型bean
  1. 自定义一个类实现FactoryBean< T >接口,并重写其getObjectgetObjectType方法

    	public class MyStudentBeanFactory implements FactoryBean<Student> {
    	    @Override
    	    public Student getObject() throws Exception {
    	        Student student = new Student();
    	        student.setName("myStudentBeanFactoryStu");
    	        return student;
    	    }
    	
    	    @Override
    	    public Class<?> getObjectType() {
    	        return Student.class;
    	    }
    	}
    
  2. 配置文件中注入factorybean

    	<bean id="studentBean" class="online.abor.others.MyStudentBeanFactory"/>
    

通过注解配置bean

  1. 在配置文件中通过context:component-scan指定需要扫描的包

    	<context:component-scan base-package="online.abor.annotation"/>
    
  2. 在类上添加注解(@Component@Controller@Service@Repository)
    注解可以添加value参数指定生成bean的id

    	@Service("userService")
    	public class UserServiceImpl implements UserService {
    	    private final UserDao userDao;
    	
    	    public UserServiceImpl(UserDao userDao) {
    	        this.userDao = userDao;
    	    }
    	
    	    @Override
    	    public void save() {
    	        System.out.println("UserServiceImpl's save()");
    	        userDao.save();
    	    }
    	}
    

    不添加value参数的话,IOC容器用的是默认的命名规则,首字母小写,其后的保持与原类名一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值