Spring容器的xml配置及注解使用

本文详细介绍了Spring框架中的IOC(控制反转)概念,包括通过XML配置文件创建bean、依赖注入、bean的作用域、静态工厂和实例工厂的使用、bean的生命周期以及后置处理器等。此外,还讨论了注解在Spring中的应用,如@Component、@Repository、@Controller和@Service,并提到了SpEL(Spring Expression Language)在配置中的作用。

Spring介绍

框架:高度抽取可重用代码的一种设计;高度的通用性;

​ 多个可重用模块的集合,形成某个领域的整体解决方案

Spring框架:容器:可以管理所有的组件;IOC和AOP

IOC(容器):Iversion Of Control 控制反转

用容器来整合框架

控制:资源的获取

  • 主动式(自己用什么资源就创建new)
  • 被动式(资源的获取交给容器创建和设置)

容器:从主动的new资源为被动的接受资源

DI(Dependency Injection):依赖注入(是IOC思想的具体实现)。容器能知道那个组件运行的时候,需要另一个组件,容器通过反射的形式,将容器中的准备好的对象注入(利用反射给属性赋值)到最初的那个组件中。

容器中对象的创建在容器创建的时候就创建了。

一个bean对应一个对象

同一个组件在ioc中是单例的。

javabean的属性名是由getter/setter方法决定的,去掉set之后将首字母小写之后得到的字符串就是属性名。

配置文件:
bean的创建原理

bean的创建就是框架利用反射new出来的bean实例

话说反射是一种效率很低的方法,所以有哪些对象是应该使用bean来创建的呢?

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="stu1" class="com.onezero.Student">
        <property name="name" value="张三"></property>
        <property name="age" value="18"></property>
    </bean>
    <bean id="stu2" class="com.onezero.Student">
        <property name="name" value="李四"></property>
        <property name="age" value="19"></property>
    </bean>
    <bean id="stu3" class="com.onezero.Student">
        <constructor-arg name="age" value="20"></constructor-arg>
        <constructor-arg name="name" value="onezero"></constructor-arg>
    </bean>
    <bean id="stu4" class="com.onezero.Student">
        <constructor-arg value="马云"></constructor-arg>
        <constructor-arg value="40"></constructor-arg>
    </bean>
</beans>

在配置文件中使用property标签是通过set方法来赋值的。通过constructor-arg可以调用有参构造器赋值。若是严格按照有参构造器中参数出现的顺序写属性,则可以省略name。

若没有严格按照构造器中给出的参数数据赋值,可以通过index指定赋给第几个参数。

若是构造器进行了重载且参数个数一样,如果想省略name需要指定type(即参数类型)

综上所述,不省略name是一种比较常见的配置方法。

通过p命名空间为bean赋值

通过get/set方法进行赋值

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="stu05" class="com.onezero.Student" p:age="19" p:name="小红"></bean>

</beans>
获取bean对象的三种方法:
//通过bean的id获取bean的实例
public void dmeo() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("ioc.xml");
        System.out.println("ioc配置完成");
        Student stu1 = (Student) ac.getBean("stu1");
        System.out.println(stu1);
    }

//通过bean的类型从IOC容器中获取bean的实例,优点是可以不用进行类型转换,缺点是若配置文件中存在多个该类型的bean,就会报错
public void demo2(){
        Student stu = ac.getBean(Student.class);
        System.out.println(stu);
    }

//改进
Student stu = ac.getBean("stu1",Student.class);
通过配置文件进行复杂的赋值:
package com.onezero;


import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class Student {
    private String name;
    private Integer age;
    private Car car;
    private List<Book> list;
    private Map<String,Object> map;
    private Set<Integer> set;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", car=" + car +
                ", list=" + list +
                ", map=" + map +
                ", set=" + set +
                ", properties=" + properties +
                '}';
    }

    public Map<String, Object> getMap() {
        return map;
    }

    public void setMap(Map<String, Object> map) {
        this.map = map;
    }

    public Set<Integer> getSet() {
        return set;
    }

    public void setSet(Set<Integer> set) {
        this.set = set;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    private Properties properties;

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    public List<Book> getList() {
        return list;
    }

    public void setList(List<Book> list) {
        this.list = list;
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
        System.out.println("有参");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Student() {
        System.out.println("对象被创建了");
    }
}

<?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:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <bean id="stu" class="com.onezero.Student">
        <property name="age" value="19"></property>

        <property name="name">
            <null></null>
        </property>
        <!--ref:引用外部bean,是严格的引用-->
        <property name="car" ref="car"></property>

        <property name="list">
            <!--为list赋值-->
            <list>
                <!--内部bean无法被外部获取到-->
                <bean class="com.onezero.Book" p:name="西游记" p:author="吴承恩" p:price="20"></bean>
                <!--使用外部引用-->
                <ref bean="book1"></ref>
            </list>
        </property>

        <property name="map">
            <map>
                <entry key="book" value-ref="book1"></entry>
                <entry key="name" value="小红"></entry>
                <entry key="num">
                    <value>126</value>
                </entry>
            </map>
        </property>

        <property name="set">
            <set>
                <value>15</value>
                <value>15</value>
                <value>155</value>
            </set>
        </property>

        <property name="properties">
            <props>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>

    </bean>

    <bean id="car" class="com.onezero.Car">
        <property name="branch" value="宝马"></property>
        <property name="price" value="300000"></property>
    </bean>

    <bean id="book1" class="com.onezero.Book" p:price="30" p:author="金鱼酱" p:name="人间告白">
    </bean>
</beans>
通过util命名空间创建集合类型的bean,方便引用
<!--util:map相当于new了一个LinkedHashMap-->   
<util:map id="map">
        <entry key="book" value-ref="book1"></entry>
        <entry key="name" value="小红"></entry>
        <entry key="num">
            <value>126</value>
        </entry>
    </util:map>

    <bean id="stu2" class="com.onezero.Student">
        <property name="map" ref="map"></property>
    </bean>
级联属性

级联属性:属性的属性(例如:car.price)

parent属性

parent:指定当前的bean的配置信息继承于哪个bean

abstract=“true”

abstract=“true”:表示当前bean的配置是一个抽象的,不能获取它的实例,只能被继承

depends-on:bean之间的依赖

bean 里面的依赖只是指bean的创建顺序罢了。若是没有依赖,创建顺序按照在配置文件中的书写顺序。若是有了依赖关系,那么先创建被依赖的bean(被依赖的bean可以是有多个)

bean的作用域

bean的作用域指bean是否是单实例的。默认情况下,bean是单实例的。

scope=“prototype”:多实例

  • 容器启动时默认不去创建多实例的bean
  • 获取的时候这个bean才会创建
  • 每次获取都创建一个新的对象

scope=“singleton”:单实例(默认)

  • 在容器启动完成之前就创建好了对象,保存到容器
  • 获取到的bean一直是一样的
静态工厂和实例工厂

工厂模式:工厂帮我们创建对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

  • 静态工厂:工厂本身不用创建对象,通过静态方法调用
    • factory-method:使用静态工厂中的那个方法
  • 实例工厂:工厂本身需要创建对象
    • factory-bean:指定使用哪个工厂
    • factory-method:使用静态工厂中的那个方法
<!--静态工厂方法创建bean-->
<bean id="stu1" class="com.onezero.factory.StaticFactory" factory-method="getStudent">
    <constructor-arg value="李四"></constructor-arg>
</bean>
<!--实例工厂创建bean-->
    <bean id="stuFactory" class="com.onezero.factory.InstanceFactory"></bean>
    <bean id="stu2" class="com.onezero.Student" factory-bean="stuFactory" factory-method="getStudent">
        <constructor-arg value="张三"></constructor-arg>
    </bean>
  • FactoryBean是Spring的一个接口,只要是这个接口的实现类,Spring就认为这是个工厂类

    步骤:写一个实现类;在spring中配置

    public class MyFactory implements FactoryBean<Book> {
        @Override
        public Book getObject() throws Exception {
            System.out.println("创建一个实例");
            Book book=new Book();
            return book;
        }
    
        @Override
        public Class<?> getObjectType() {
            return Book.class;
        }
    }
    

    FactoryBean:获取的时候才创建实例;ioc启动的时候不会创建实例

bean的生命周期

单实例的bean容器启动时就创建好,容器关闭就会销毁创建的bean

多实例bean获取是才会创建。

在spring中也可以通过方法来指定生命周期。

单例bean的生命周期:构造器–初始化方法–(容器关闭)销毁方法

多例bean的生命周期:(获取bean)构造器–初始化方法 就算是容器关闭也不会调用销毁方法

<bean id="book" class="com.onezero.Book" init-method="init" destroy-method="destory" scope="prototype"></bean>
 private ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("ioc5.xml");
//ApplicationContext接口中没有close方法
bean的后置处理器

后置处理器:可以在bean的初始化前后调用方法。

使用步骤:实现 BeanPostProcessor接口;在配置文件中注册

public class BeanPostProcessorTest implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName+":将要调用初始化方法.这个bean是"+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
}

<bean id="beanPostProcessor" class="com.onezero.test.BeanPostProcessorTest"></bean>
引用外部属性文件

数据库连接池作为单实例是最好的,一个项目就一个连接池。

<context:property-placeholder location="classpath:durid.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="username" value="${usernameH}"></property>
    <property name="password" value="${password}"></property>
    <property name="url" value="${url}"></property>
    <property name="driverClassName" value="${driver}"></property>
</bean>

因为username是Spring中的关键字,所以在.properties时不能使用username,可以改为jdbc.username

自动装配

autowired(xml)

  • byType
  • byName
  • constructor

通过注解@Autowored实现自动装配,它可以用于成员变量、构造器及方法,不过只能用于装配引用。

SpEL:Spring Expression Language
#{}
${}
//调用静态方法
#{T(全类名).方法}
通过注解将bean加入容器
  • @Component
  • @Repository:持久层
  • @Controller:控制层
  • @Service:业务层
    之后要在xml中加入
<context:component-scan base-package=""/>

Spring 会扫描所有base-package下的类。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值