配置元数据描述了Spring容器在应用程序中是如何实例化、配置和组装对象的。配置的方式有XML配置、注解配置、Java配置。
Spring的配置至少需要一个或多个由容器管理的bean.基于XML的配置元数据,需要用
id属性是用于标识单个bean定义的字符串,它的值指协作对象,class属性定义bean的类型,并使用完全限定的类名。
应用举例:
bean的命名:在基于XML配置元数据中,使用id或name属性来指导bean标识符。bean的命名遵循一个小写字母开头的骆驼命名规则。
(1)作用域配置
Spring 中创建bean时,可以指定作用域,作用域有以下5种类型
原型(prototype)每次获取Bean时生成一个新的实例。
请求(request)作用域是单个http请求,单个http请求只有Bean的一个实例。一旦请求完成,bean实例将被销毁。
会话(session)作用域是单个会话,单个会话只有Bean的一个实例。一旦会话结束,bean实例将被销毁。
全局会话(global-session)在Portlet应用程序中使用,每个全局会话只有Bean的一个实例。普通Servlet应用中与会话作用域无区别。
(2)设置初始化方法和销毁方法
Bean在创建时,需要执行一些资源(数据库、套接字、文件)申请等初始化工作,可以在Bean的初始化回调方法中处理,此方法由Spring容器调用。
同样Bean在销毁时,需要执行一些资源(数据库、套接字、文件)申请等销毁工作,可以在Bean的销毁回调方法中处理,此方法由Spring容器调用。
应用举例:
xml文件配置
创建初始化方法和销毁方法
public class Customer {
//....
public void init() {
System.out.println("初始化...");
}
public void close() {
System.out.println("销毁...");
}
}
运行效果:
Spring IoC容器需要在应用启动时进行实例化。在实例化过程中,IoC容器会从各种外部资源加载配置元数据,提供给ApplicationConext构造函数。
有两种IoC容器:
ApplicationContext容器是更高级更常用的容器,继承并扩展了BeanFactory的功能。同样ApplicationContext
本身是一个Java接口,常用的实现类是:
FileSystemXmlApplicationContext
: 通过文件路径加载bean的xml配置文件ClassPathXmlApplicationContext
: 通过类路径加载bean的xml配置文件WebXmlApplicationContext
: 通过web网址加载bean的xml配置文件举例:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Hello
{
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");// ApplicationContext容器加载application.xml
}
}
ApplicationContext提供的getBean()方法可用于检索bean实例。
应用举例:
//创建并配置bean
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
//检索配置了的bean实例
Customer customerBean = (Customer) context.getBean("customerBean");
//使用bean实例
customerBean.displayInfo();
最后应用结束时需要关闭容器,释放资源,容器中的所有bean也将被销毁。
context.close();
应用举例:
((ClassPathXmlApplicationContext) context).close();
Bean通过名称进行区分,每个Bean至少有一个名称,通过Bean名称,可以引用其他Bean。命名方式有三种:
Bean的实例化方法有两种:
(1)构造函数实例化
Customer.java类如下所示,该类含有有参构造函数和无参构造函数
package com.herry.demo;
public class Customer {
String name;
//无参构造函数
public Customer() {
}
//有参构造函数
public Customer(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void displayInfo() {
System.out.println("Hello: "+ name);
}
public void init() {
System.out.println("初始化...");
}
public void close() {
System.out.println("销毁...");
}
}
XML配置调用无参构造函数实例化Bean
XML配置调用有参构造函数实例化Bean
注意constructor-arg和property在参数传递的用法不同:
(2) 调用静态或实例工厂方法
添加Store.java文件
package com.herry.demo;
public class Store {
//静态方法
public static Customer crateCustomer1()
{
Customer customer=new Customer();
customer.setName("herry");
return customer;
}
//工厂方法
public Customer crateCustomer2()
{
Customer customer=new Customer();
customer.setName("herry");
return customer;
}
}
调用静态工厂方法实例化Bean,通过调用类中的factory-method特性所指定的静态方法实现。
使用实例工厂方法实例化Bean,需要加入factory-bean特性,通过该特性引用包含实例工厂方法的工厂Bean.
由Spring容器创建的Bean的生存期称为Bean作用域。作用域的设定使用
默认的情况下,Spring容器在启动阶段创建Bean,优点是尽可能早的发现配置错误。Spring,XML配置中
Bean定义回调方法,这些方法可以在Bean生命周期的任何特点时间点由容器调用。如基于XML配置的
依赖注入的基本原则是应用程序对象不应该负责它们所依赖的资源或协作者,而是应该由IoC容器处理对象创建和依赖注入,从而导致资源查找的外部化。
关于依赖注入的优势参考以下知乎回答:spring的依赖注入到底有什么优势? - 牛岱的回答 - 知乎 https://www.zhihu.com/question/27053548/answer/575335901
xml配置文件中,在bean的定义中可配置该bean的依赖项,通常使用的配置方式有2种:
有以下代码:
类A和组件B,A依赖于B,A的方法importantMethod用到了B。若B是接口,且有多个实现,则A的可重用性大大降低。依赖注入,即接管对象的创建工作,并将对象的引用注入到需要该对象的组件。依赖注入框架会分别创建对象A和对象B,并将对象B注入到对象A中。
1、基于构造函数注入
对于上述代码,利用构造函数注入的形式如下:
构造函数注入在组件创建期间被执行。依赖项被表示为构造函数的参数,容器通过检查Bean定义中指定的构造函数参数来确定调用哪个构造函数。
使用
应用举例:
(1)编写Customer类
package com.herry.demo;
public class Customer {
String name;
//有参构造函数
public Customer(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage()
{
return "Hello: "+ name;
}
}
(2)编写MessagePrinter类,该类依赖Customer类
package com.herry.demo;
import com.herry.demo.Customer;
public class MessagePrinter {
private Customer customer;
//定义有参构造函数
public MessagePrinter(Customer customer) {
this.customer=customer;
}
//使用注入的Customer的具体逻辑
public void displayInfo() {
System.out.println(this.customer.getMessage());
}
}
(3)编写应用主类Hello
package com.herry.demo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Hello
{
public static void main(String[] args) {
// @SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
MessagePrinter printer=context.getBean(MessagePrinter.class);
printer.displayInfo();
((ClassPathXmlApplicationContext) context).close();
}
}
(4)创建配置文件
测试结果:
2、基于Setter方法注入
对于举例中的代码使用Setter方法依赖注入形式如下:
A类中新增setB方法,该方法被spring框架调用,以注入B的一个实例。
Setter注入是在Bean实例化完成后执行。实例化后,通过调用bean的setter方法完成。
工程的目录结构如下:
(1) Customer类与上面一样不做任何修改
(2)MessagePrinter类修改为如下:
package com.herry.demo;
import com.herry.demo.Customer;
public class MessagePrinter {
private Customer customer;
public MessagePrinter()
{
}
public Customer getCustomer() {
return customer;
}
//定义setter函数,setter方法注入bean
public void setCustomer(Customer customer) {
this.customer=customer;
}
//使用注入的Customer的具体逻辑
public void displayInfo() {
System.out.println(this.customer.getMessage());
}
}
(3) 主类也不要修改,做了如下调整,也可不变
package com.herry.demo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Hello
{
public static void main(String[] args) {
// @SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
MessagePrinter printer=(MessagePrinter)context.getBean("messagePrinter");
printer.displayInfo();
((ClassPathXmlApplicationContext) context).close();
}
}
(4) 配置文件修改如下
配置文件中,Customer类通过构造函数方式实例化Bean;messagePrinter对象通过配置property元素来调用setter方法以设置值。
(5)运行结果如下:
参考:https://www.cnblogs.com/xp2h/p/12373037.html