Spring的基本用法(大全)

Spring的简介

基于依赖注入的核心机制、基于AOP的声明式事务管理,与多种持久层技术的整合。使用Spring框架必须使用Spring Core Container只要由org.springframework.core、org.springframework.beans、org.springframework.context、org.springframework.expression四个包及其子包组成。

  1. 像大工厂一样,负责创建、管理所有Java对象,这些Java对象就是Bean。
  2. 管理容器中Bean之间的依赖关系
  3. 本质是通过XML配置文件来驱动Java代码

使用Spring管理bean

Spring容器是一个工厂。

Bean是Spring容器管理的对象,一切Java对象都可以是Bean

bean与Java Bean的不同

  • 写法不同:Java Bean必须遵守特定的规范,必须给每个属性提供对应的getter和setter方法,而Bean只需提供setter方法。
  • 用处不同:Bean是Java实例、Java组件,JavaBean通常作为DTO(数据传输对象)来封装值对象,来传递参数
  • 生命周期不同:JavaBean作为值对象传递,不接受任何容器管理其生命周期。Bean由Spring管理生命周期。
<?xml version="1.0" encoding="UTF-8"?>
<beans>
 <!-- 配置db.properyies文件位置 -->
    <bean id="configurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
        <property name="locations" value="classpath:db.properties"></property>
    </bean>
</beans>

<bean/>驱动spring以反射方式调用该类无参的构造器。id为Bean的唯一标识,通过id属性值访问Bean和管理Bean之间的依赖。class指定Bean的实现类。

<property/>驱动spring在底层以反射执行setter方法赋值。 name属性决定执行哪个setter方法,value或ref决定执行setter方法传入的参数。ref可指定一个bean属性,该属性用于引用容器内中其他Bean实例的id属性值。

<value><property/>的子元素相当于value,可指定调用setDriverClass()方法。的参数值为com.mysql.jdbc.Driver。设值注入。现在用得少。

 

程序通过Spring容器来访问容器中的Bean,ApplicationContext是Spring容器最常用的接口,有如下两种实现类:

  • ClassPathXmlApplicationContext:从类加载路径下搜索配置文件,根据配置文件创建Spring容器。通常用这个。
  • FileSystemXmlApplicationContext:从文件系统的相对路径
public class BeanTest
{
    public static void main(String[] args)throws Exception{
//  创建Spring容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
        // 获取id为person的Bean
        Person p = ctx.getBean("person",Person.Class);
 
    }
}

Spring的核心机制:依赖注入(DI ,Dependency Injection)

依赖:A对象调用B对象的方法,即A对象依赖于B对象。

注入普通的属性值,还可以注入其他Bean的引用。当某个Java实例需要其他Java实例时,系统自动提供所需实例,无需程序显示获取。

工厂模式和被依赖对象的接口耦合,被依赖对象交给工厂创建。

现在只需被动的等待Spring容器注入。

实现方法:

  • 设值注入。IOC(控制反转)容器使用成员变量的setter方法来注入被依赖对象
  • 构造注入。IOC(控制反转)容器使用构造器来注入被依赖对象

Spring推荐面向接口编程。不论调用者还是被依赖者都定义为接口。也可以通过注解,利用反射创建实例。

public class Chinese implements Person{
    private Axe axe;
//设值注入所需的setter方法
    public void setAxe(Axe axe){
        this.axe=axe;
    }
    public void useAxe(){
// 实现Person接口的useAxe方法
        System.out.println(axe.chop());
//调用chop方法,表明Person对象依赖于axe对象
    }
}

使用XML配置文件指定实例之间的依赖关系。

构造注入

通俗来说,就是驱动Spring底层以反射方式执行带指定参数的构造器。

问题:<bean/>总是驱动Spring执行无参的构造器来创建对象,怎么驱动Spring执行有参数的构造器???

答案是<contructor-arg  />子元素。<contructor-arg  />子元素代表一个构造器参数。

public class Chinese implements Person{
    private Axe axe;
//构造注入所需的带参数的构造器
    public Chinese(Axe axe){
        this.axe=axe;
    }
    public void useAxe(){
// 实现Person接口的useAxe方法
        System.out.println(axe.chop());
//调用chop方法,表明Person对象依赖于axe对象
    }
}

//对应的配置文件添加<contructor-arg  />子元素

优先依赖的,优先注入。

建议:以设值注入为主,构造注入为辅。依赖关系无需变化的注入,就是用构造注入。

Spring的核心接口

ApplicationContextBeanFactory,ApplicationContext是BeanFactory的子接口

BeanFactory

方法

  • boolean containsBean(String name):
  • <T> T getBean(Class<T> requiredType)返回属于requiredType类型的Bean实例。Object getBean(String name)容器id为name的Bean实例
  • Class<?> getType(String name)

注意事项

  1. 创建BeanFactory实例时,必须提供XML配置文件作为参数,XML配置文件通常使用Resource对象传入。(Resource接口是Spring提供的资源访问接口)
  2. 如果需要加载多个配置文件来创建Spring容器,利用ApplicationContext来创建SessionFactory的实例。
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml","service.xml");

ApplicationContext

使用ApplicationContext实例作为容器,Spring的上下文。

允许以声明式方式操作容器,除了提供BeanFactory所支持的全部功能外,还支持如下功能:

  • ApplicationContext默认会预初始化所有的singleton Bean,也可通过配置取消预初始化。不加特殊配置,Bean默认为singleton行为
  • ApplicationContext继承MessageSource接口,提供国际化支持。
  • 资源访问,如URL和文件
  • 事件机制
  • 同时加载多个配置文件
  • 以声明式方式启动创建Spring容器

优先使用ApplicationContext

<bean />元素指定lazy-init="true"阻止容器预初始化该Bean

ApplicationContext的国际化支持

ApplicationContext继承MessageSource接口,提供国际化支持

String  getMessage(String code,Object[] args,Locale loc)

String getMessage(String code,Object[] args,Locale loc)

ApplicationContext的事件机制

ApplicationContext的事件机 制是观察者设计模式实现。通过ApplicationEvent(容器事件)和ApplicationListener(监听器)接口实现事件处理。

事件源、事件和事件监听器组成

Spring容器中的Bean

  • 开发Bean
  • 配置Bean

Bean的基本定义和别名

<beans />元素是Spring的根元素,属性如下:

  • default-merge:指定所有Bean默认的merge行为
  • default-lazy-init:指定所有Bean默认的延迟初始化
  • default-autowire:自动装配行为。no、byName、byType、constructor、autodetect
  • default-autowire-candidates:指定所有Bean默认是否作为作为自动装配的候选Bean。不做自动装配设为false。
  • default-init-method:初始化方法
  • default-destroy-method:回收方法

定义Bean时,通常指定两个属性:

  • id:Bean的唯一标识
  • class:实现类
  • name:指定别名,多个别名可用逗号、冒号、空格
  • <alias />子元素为已有的Bean指定别名。name:指定Bean实例的标志,alias:别名

容器中Bean的作用域

5种作用域:

  • singleton(常用):默认单例,整个Spring IOC容器中,singleton只生成一个bean实例
  • prototype(常用):每次通过容器的getBean()方法获取prototype作用域的Bean,都将产生新的实例
  • request:对于一次HTTP请求,request作用域的Bean就只生成一个实例。Web应用中生效
  • session:对于一次HTTP会话,session作用域的Bean就只生成一个实例。Web应用中生效
  • global session:每个全局的HTTP session对应一个作用域。仅在使用portlet context有效,Web应用中生效。

使用自动装配注入合作者Bean

通过<bean />的autowire属性指定或<beans />的default-autowire指定。属性值如下:

  • no
  • byName:根据setter的方法名。没找到匹配BeanSpring不做任何事情。 
  • byType:根据setter的方法参数类型。容器包含多于一个的匹配参数类型实例就会抛出异常。
  • constructor:与byType相似,区别在于自动匹配构造器的参数。如果找不到匹配与构造器参数类型匹配的Bean就会抛出错误
  • autodetect:Spring根据Bean内部结构,自行决定使用construct或byType策略。如果是默认构造函数就会使用byType。

注入嵌套Bean

如果某个Bean所依赖的Bean不想被Spring容器直接访问,可以使用嵌套Bean。

嵌套Bean:把<bean />作为<property/>或<contructor-args/>的子元素,那么该<bean/>元素配置的Bean仅仅作为setter注入、构造注入的参数。由于容器不能获取嵌套Bean,所以不用指定id

本质上与使用ref引用容器中的另一个Bean一样。

小贴士

  • 形参类型是基本类型、String、日期等,用value指定字面值即可。
  • 形参类型是复合类(如Person、Dog、DataSource等Java对象)作为实参。1.使用ref引用容器中已配置的Bean(Java对象)2.使用<bean/>元素配置嵌套Bean

注入集合值

在<property/>元素下添加<list/>、<set/>、<map/>和<props/>设置集合参数值

<property name="">
<list>
<!--每个value、ref、bean都配置List元素 -->
    <value>小学</value>
    <value>中学</value>
</list>
<property/>
<property name="">
<map>
    <entry key="" value=""/>
    <entry key="" value=""/>
</map>
<property/>
<property name="">
<map>
    <entry key="" value-ref=""/>
    <entry key="" value-ref=""/>
</map>
<property/>

<property name="">
    <props>
<!--每个key、value只能是字符串 -->
        <prop key="属性名"></prop>
        <prop key="血压">125</prop>
        <prop key="身高">163</prop>
    <props/>
<property/>

<property name="">
<set>
<!--每个value、ref、bean都配置set元素 -->
    <value>普通字符串</value>
    <bean class="类的路径" />
    <ref bean="类名" />
    <list>
        <value></value>
        <set>
            <value type="int"></value>
        </set>
    </list>
</set>
<property/>

组合属性

除最后一个属性外,其他属性不能为null

 

Java配置管理

Java配置类的三个Annotation

  • @Configuration:用于修饰配置类
  • @Bean:修饰一个方法,将该方法的返回值定义成容器中的一个Bean
  • @Value:修饰Field,为该Field配置一个值
  • @Import:修饰Java配置类,用于向当前Java配置类中导入其他Java配置类
  • @Scope:修饰一个方法,方法对应的Bean的作用域
  • @Lazy:修饰一个方法,方法对应的Bean是否延迟初始化
  • @DependsOn:修饰一个方法,指定在初始化该方法对应的Bean及其依赖关系之前初始化指定的Bean。

以XML配置方式为主,需要在XML配置中加载Java类配置

<!-- 加载Java配置类 -->
<bean class="org.crazyit.app.config.AppConfig">

以Java类配置为主,借助@ImportResources注解修饰Java配置类

@Configuration
// 导入XML配置
@ImportResources("classpath:/beans.xml")

创建Bean的3种方式

  • 调用构造器创建Bean
  • 调用静态工厂方法创建Bean
  • 调用实例工厂方法创建Bean

调用构造器创建Bean

如果不采用构造注入,Spring底层默认调用Bean类的无参构造器创建实例。所有基本类型初始化为0或false,所有引用类型初始化为null。根据配置文件实例化被依赖的Bean,为Bean注入依赖关系,最后将一个完整的Bean实例返回程序。

调用静态工厂方法创建Bean

<bean />必须指定class属性。此时class指定的是静态工厂类。还需要使用factory-method属性指定静态工厂方法。Spring调用静态工厂方法返回Bean实例。

public class BeingFactory{
    //返回Being实例的静态工厂方法
    //	参数arg决定返回哪个Being类的实例
	public static Being getBeing(String arg){
		if(arg.equalsIgnoreCase("dog")){
			return new Dog();
//			返回Dog实例
		}
//		否则返回Cat实例
		else{
			return new Cat();
		}
	}
}
<bean class="BeanFactory" factory-method="getBeing">
<!-- 配置静态工厂方法的参数 -->
<constructor-arg value="dog"/>
<property name="msg" value="the dog"/>
</bean>

调用实例工厂方法创建Bean

实例工厂和静态工厂只有一点不同:调用静态工厂方法只需使用工厂类,而调用实例工厂需要工厂实例。

配置静态工厂方法使用class指定静态工厂类,配置实例工厂使用factory-bean指定工厂实例。

使用实例工厂时,<bean/>无须class属性,Spring容器调用实例工厂的工厂方法创建Bean实例。

实例工厂方法创建<bean/>元素时需要指定的属性:

  • factory-bean:指定工厂Bean的id
  • factory-method:指定实例工厂的工厂方法

抽象Bean与子Bean

<bean/>元素下添加abstract="true",不指定class就是抽象Bean,不能被实例化,只能被继承

<bean/>元素下添加parent="父Bean的id",该bean是一个子bean.

Bean继承和Java继承的区别

  • Spring中子Bean与父Bean可以是不同类型,Java继承保证子类是特殊父类
  • Bean的继承是实例间的关系,主要表现在参数值的延续。Java继承是类之间的关系,主要表现在方法、属性的延续。
  • 子Bean不能作为父Bean使用,不具备多态性,Java继承子类实例可以当父类实例使用

工厂Bean:与前面不同,Spring的一种特殊Bean,必须实现FactoryBean接口。返回该Bean实例的getObject()方法的返回值。开发者实现getObject()方法。(返回某个类型的值)

容器中Bean的生命周期

Spring可以管理singleton作用域的Bean的生命周期,Spring可以精确的知道该Bean何时被创建、初始化完成、何时准备销毁该实例。

prototype作用域的Bean,Spring仅仅负责创建。其他就交给客户端代码管理,无法管理。

注入依赖关系之后

  • 使用init-method属性:指定某个方法在Bean注入依赖关系之后自动执行
  • InitializingBean接口:在为Bean注入依赖关系之后实现void afterPropertiesSet() throws Exception

Bean销毁之前

  • 使用destroy-method属性:指定某个方法在Bean销毁之前自动执行
  • 实现disposableBean接口:void destroy() throws Exception

获取其他Bean的属性值

PropertyPathFactoryBean用来获取其他Bean的属性值。(实际上就是getter方法的返回值)

  • 调用哪个对象:由PropertyPathFactoryBean的setTargetObject(Object targetObject)方法指定
  • 调用哪个getter方法:由PropertyPathFactoryBean的setPropertyPath(String propertyPath)方法指定。
<bean class="" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="person"/>
<property name="propertyPath" value="son"/>
</bean>

<util:property-path/>作为PropertyPathFactoryBean简化配置。id属性:指定getter方法的返回值定义成名为id的Bean实例。path:指定哪个Bean实例、哪个属性暴露出来。

获取Field值

通过FieldRetrievingFactoryBean类,可访问类的静态Field或对象的实例Field值。可将获取的值注入到其他Bean,也可直接定义新的Bean。<util:constant/>

<bean class="" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetClass" value="java.sql.Connection"/>
<property name="targetField" value="TRANSACTION_SERIALIZABLE"/>
</bean>

获取方法返回值

通过MethodInvokingFactoryBean工厂Bean,可以获取任意类的类方法。

SpEL

Spring表达式语言即SpEL。略

Spring的零配置支持

  • @Component:标注普通Java Bean类,首字母小写,其他不变
  • @Controller:控制器组件类
  • @Service:业务逻辑组件类
  • @Repository:DAO组件类
  • @Scope:作用域
  • @Resource(name=" ")和<property/>的ref效果相同,可以省略name。修饰setter方法或实例变量
  • @PostConstruct修饰的方法是Bean创建之后执行方法
  • @PreDestroy修饰的方法是Bean销毁之前执行方法
  • @DependsOn:强制初始化其他Bean
  • @Lazy:指定Bean是否取消预初始化。延迟。
  • @Autowired:自动装配,可以修饰setter方法、普通方法、实例变量和构造器。默认采用byType自动装配策略
  • @Qualifier:根据Bean的id执行自动装配

 

自动扫描指定包及其子包下的所有Bean类<context:component-scan base-package="org.crazyit.app.service"/>

<context:component-scan base-package="org.crazyit.app.service">
    <context:include-filter type="regex" expression=".*Chinese"/>
    <context:include-filter type="regex" expression=".*Axe"/>
</context:component-scan>

<context:exclude-filter>或<context:include-filter>子元素指定Spring Bean类,只要位于指定路径下的Java类满足这个规则,就会当成Bean类处理。

type:指定过滤器类型

expression:过滤器所需要的表达式

Spring内建支持的4种过滤器:annotation(annotation过滤器)、assignable(类名过滤器)、regex(正则表达式)、aspectj(aspectj过滤器)

 

资源访问

资源=>XML配置文件、二进制流等各种类型文件

Resource接口的实现类有UrlResource等

  1. 访问网络资源
  2. 访问类加载路径下的资源
  3. 访问文件系统资源
  4. 访问应用相关资源
  5. 访问字节数组资源

ApplicationContext中使用资源

1.使用ApplicationContext实现类指定访问策略

  • ClassPathXmlApplicationContext:对应使用ClassPathResource进行资源访问
  • FileSystemXmlApplicationContext:对应使用FileSystemResource进行资源访问
  • XmlWebApplicationContext:对应使用ServletContextResource进行资源访问

2.使用前缀指定访问策略

http:、ftp:等前缀,用来确定对应的资源访问策略。

3.classpath*:前缀用法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章