一、基于 XML 的 Bean 的配置——通过全类名(反射)

<bean

<!-- id: bean 的名称在IOC容器内必须是唯一的若没有指定,则自动的将全限定类名作为 改 bean 的名称-->id="hello"

<!-- 通过全类名的方式来配置 bean -->class="com.atguigu.spring.helloworld.HelloWorld">

</bean>

1.通过属性注入

即通过 setXxx() 方法注入 Bean 的属性值或依赖的对象。

使用 <property name="" value="" ref=""/> 元素,其中 name 值为对应 Bean 属性名称,value 指定对应属性值,ref 引用其他 Bean,value 属性和 ref 属性不可以同时存在。

也可以通过 <value></value> 子节点的方式指定属性值。

e:

<bean id="helloWorld" class="com.nucsoft.spring.helloworld.HelloWorld">
  <property name="hello" value="spring"/>
  <property name="world">
    <value>spring</value>
  </property>
</bean>

注意:在此种方式下,要配置的 Bean 必须存在空参构造器。

2.通过构造器注入

通过构造方法注入属性值或依赖的对象。

使用 <constructor-arg value="" index="" name="" ref="" type=""/> 元素,value 属性为对应的参数指定值,ref 引用其他 Bean。不可同时存在。

通过 name 属性、index 属性、type属性提供了三种注入方式:

(1)name:按照构造器参数名匹配入参

<bean id="car1" class="com.nucsoft.spring.helloworld.Car">
  <constructor-arg name="brand" value="奥迪"/>
  <constructor-arg name="corp" value="上海"/>
  <constructor-arg name="price" value="400000"/>
</bean>

(2)index:按照索引匹配入参

<bean id="car2" class="com.nucsoft.spring.helloworld.Car">
  <constructor-arg index="0" value="大众"/>
  <constructor-arg index="1" value="10000"/>
</bean>

(3)type:按照类型匹配入参

<bean id="car3" class="com.nucsoft.spring.helloworld.Car">
  <constructor-arg type="java.lang.String" value="宝马"/>
  <constructor-arg type="double" value="200000"/>
</bean>

注意:Spring 虽然提供了通过构造器的方式进行注入,但是并不推荐使用此种方式。

3.细节问题

(1)若注入的属性值包含特殊字符,可以使用 <![CDATA[]]> 包含该属性值。

如:

<bean id="car4" class="com.nucsoft.spring.Car">
  <property name="brand">
    <value><![CDATA[<BM>]]> </value>
  </property>
  <property name="corp" value="德国"/>
  <property name="maxSpeed" value="230"/>
  <property name="price" value="20000000"/>
</bean>

(2)可以通过 <ref> 元素或 ref 属性为 Bean 的属性或构造器指定对 Bean 的引用。

如:

e1:

<bean id="service" class="com.nucsoft.spring.Service"/>
<bean id="action" class="com.nucsoft.spring.Action">
<property name="service" ref="service"/>
</bean>

e2:

<bean id="feather" class="com.nucsoft.spring.Feather">
  <property name="length" value="13"/>
</bean> <bean id="bird" class="com.nucsoft.spring.Bird">
  <constructor-arg name="birdName" value="smallBird"/>
  <constructor-arg name="feather" ref="feather"/>
</bean>

(3)内部Bean:可以在属性或构造器里包含 Bean 的声明,内部 Bean 不需要指定 id,同时在别的地方也无法引用。

如:

e1:

<bean id="action" class="com.nucsoft.spring.Action">
  <property name="service">
  <bean class="com.nucsoft.spring.Service"/>
  </property>
</bean>

e2:

<bean id="bird" class="com.nucsoft.spring.Bird">
  <constructor-arg name="birdName" value="smallBird"/>
  <constructor-arg name="feather">
    <bean class="com.nucsoft.spring.Feather">
      <property name="length" value="13"/>
    </bean>
  </constructor-arg>
</bean>

4.为引用类型(字符串或对象)注入 Null 值

<bean id="bird" class="com.nucsoft.spring.Bird">
  <constructor-arg name="birdName" value="smallBird"/>
  <constructor-arg name="feather">
    <null/>
  </constructor-arg>
</bean>

5.为级联属性注入

(1)通过属性

<bean id="feather" class="com.nucsoft.spring.Feather">
  <property name="length" value="44"/>
</bean> <bean id="bird" class="com.nucsoft.spring.Bird">
  <property name="birdName" value="smallBird"/>
  <property name="feather" ref="feather"/>
  <property name="feather.length" value="23"/>
</bean>

(2)通过构造器

<bean id="feather" class="com.nucsoft.spring.Feather">
<property name="length" value="44"/>
</bean>
<bean id="bird2" class="com.nucsoft.spring.Bird">
<constructor-arg name="birdName" value="bigBird"/>
<constructor-arg name="feather" ref="feather"/>
<property name="feather.length" value="33"/>
</bean>

注意:设置级联属性的前提是,级联属性所属对象已经被注入到容器中。同时需要为级联属性所属对象提供 getXxx() 方法。

6.集合属性

(1)集合性质的类型:List,Set,Map 和 数组

(2)使用 <list>,<set>,<map> 来配置集合属性,其中数组和 List 都使用 <list>

(3)List:通过引用外部 Bean 或 创建内部 Bean 的方式

<bean id="department" class="com.nucsoft.spring.Department">
  <property name="deptName" value="dept01"/>
</bean> <bean id="company" class="com.nucsoft.spring.Company">
  <property name="companyName" value="ICBC"/>
  <property name="departments">
    <list>
      <ref bean="department"/>
      <bean class="com.nucsoft.spring.Department">
        <property name="deptName" value="dept02"/>
      </bean>
    </list>
  </property>
</bean>

测试:

private ApplicationContext ctx = null;

@Before
public void init() {
  ctx = new ClassPathXmlApplicationContext("spring/ApplicationContext.xml");
} @Test
public void test01() {
  Company com = ctx.getBean(Company.class);
  System.out.println(com);
}

输出:

Company{companyName='ICBC', departments=[Department{deptName='dept01'}, Department{deptName='dept02'}]}

(4)Set:与 List 类似。不做重复说明。

(5)Map: 在<map> 标签中使用多个 <entry> 子标签:简单字面值使用属性 key 和 value 来定义,Bean 的引用通过 key-ref 和 value-ref 属性定义。

如:

<bean id="emp02" class="com.nucsoft.spring.Employee">
  <property name="employeeName" value="emp02"/>
  <property name="age" value="23"/>
</bean> <bean id="department" class="com.nucsoft.spring.Department">
  <property name="deptName" value="dept01"/>
</bean>
<bean id="department02" class="com.nucsoft.spring.Department">
  <property name="deptName" value="dept02"/>
</bean> <bean id="company" class="com.nucsoft.spring.Company">
  <property name="companyName" value="ICBC"/>
  <property name="departments">
    <map>
      <entry key-ref="department" value-ref="emp01"/>
      <entry key-ref="department02" value-ref="emp02"/>
    </map>
  </property>
  <property name="strs">
    <map>
      <entry key="key01" value="value01"/>
      <entry key="key02" value="value02"/>
    </map>
  </property>
</bean>

测试:

private ApplicationContext ctx = null;

@Before
public void init() {
  ctx = new ClassPathXmlApplicationContext("spring/ApplicationContext.xml");
} @Test
public void test01() {
  Company com = ctx.getBean(Company.class);
  System.out.println(com);
}

输出:

Company{companyName='ICBC', departments={Department{deptName='dept01'}=Employee{employeeName='emp01', age=12}, Department{deptName='dept02'}=Employee{employeeName='emp02', age=23}}}

注意:不能在 <entry> 标签中定义 Bean 标签,不支持。

(6)Properties 类型的属性:和 Map 类似,在 <props> 标签中使用 <prop> 子标签, 每个 <prop> 子标签必须定义 key 属性。

<bean id="DataSourceId" class="com.nucsoft.spring.DataSourceBean">
  <property name="propertiesInfo">
    <props>
      <prop key="user">root</prop>
      <prop key="password"></prop>
      <prop key="jdbcUrl">jdbc:mysql:///test</prop>
      <prop key="driverClass">com.mysql.jdbc.Driver</prop>
    </props>
  </property>
</bean>

7.定义单独的集合 Bean

使用基本的集合标签定义集合时,不能将集合作为独立的 Bean 定义,导致其他 Bean 无法引用该集合,所以无法在不同的 Bean 之间共用。

可以使用 util schema 里的集合标签定义独立的集合 Bean。需要注意的是,定义的集合 Bean 与 <bean> 标签是同级别的。

<bean id="company" class="com.nucsoft.spring.Company">
  <property name="companyName" value="ICBC"/>
  <property name="departments" ref="departments"/>
</bean> <util:list id="departments">
  <bean class="com.nucsoft.spring.Department">
    <property name="deptName" value="dept01"/>
  </bean>
  <ref bean="department02"/>
</util:list>

可以定义到外部的集合 Bean 有:

8.使用 p 命名空间,简化 XML 配置文件

<bean id="bird3" class="com.nucsoft.spring.Bird" p:birdName="smallBird" p:feather-ref="feather"/>

二、基于 XML 的 Bean 的配置——通过工厂方法

1.通过静态工厂方法

直接调用某一个类的静态方法,可以返回一个 Bean 的实例。通过 class 属性来指定全类名,使用 factory-method 来指定生成 bean 的静态方法。使用 constructor-arg 为静态方法传入参数。如:

<bean class="java.text.DateFormat" id="dateFormat" factory-method="getDateInstance">
  <constructor-arg value="1"/>
</bean>
@Test
public void test04() {
  DateFormat dateFormat = (DateFormat) ctx.getBean("dateFormat");
  System.out.println(dateFormat);
}

适用情况:官方或第三方提供的通过静态方法生成 bean 对象,不需要我们再创建,对应的 Bean 类一般是通过 newInstance 软编码的方式来创建。

2.通过实例工厂方法:将对象创建的过程封装到另外一个对象的方法里。

(1)首先要创建和配置一个含有工厂方法的 Bean

(2)在另一个 bean 配置中调用含有工厂方法 bean 的非 static 方法(即工厂方法)来返回一个 bean 的实例,factory-bean:指向已经创建好的工厂 bean ,factory-method:实例化工厂方法,construtor-arg:为实例工厂方法传入参数。

如:

工厂 Bean 的配置:

<bean class="java.text.SimpleDateFormat" id="simpleDateFormat">
  <constructor-arg value="yyyy-MM-dd"/>
</bean>

目标 Bean 的配置:

<bean factory-bean="simpleDateFormat" factory-method="parse" id="date">
  <constructor-arg value="2012-02-24"/>
</bean>

测试:

@Test
public void test05() {
  Date date = (Date) ctx.getBean("date");
  System.out.println(date);
}

控制台输出:

Fri Feb 24 00:00:00 CST 2012

三、基于 XML 的 Bean 的配置——通过 FactoryBean 配置 Bean

1.Spring 中有两类 Bean,一种是普通 Bean,另外一种是工厂 Bean,即 FactoryBean

2.工厂 Bean 与普通 Bean 不同,其返回的对象不是指定类的一个实例,其返回的是该工厂 Bean 的 getObject() 方法返回的对象

3.具体操作

(1)目标工厂 Bean 需要实现 FactoryBean 接口

(2)返回的对象为 getObject() 方法返回的对象。

如:

工厂 Bean:

/**
* @author solverpeng
* @create 2016-07-19-11:45
*/
public class DepartmentFactoryBean implements FactoryBean<Department>{
@Override
public Department getObject() throws Exception {
Department department = new Department();
department.setDeptName("dept01");
department.setEmployee(new Employee());
return department;
} @Override
public Class<?> getObjectType() {
return Department.class;
} @Override
public boolean isSingleton() {
return true;
}
}

Spring Config 配置:

<bean class="com.nucsoft.spring.bean.DepartmentFactoryBean" id="department"/>

测试:

@Test
public void test06() {
  Department department = (Department) ctx.getBean("department");
  System.out.println(department);
}

三、基于注解的 Bean 的配置

前提:需要导入 spring-aop-4.0.0.RELEASE.jar 包

1.在 classpath 中扫描组件(component scanning):Spring 能够从 classpath 下自动扫描和实例化具有特定注解的组件。

2.特定的组件包括:

(1)@Component:基本注解,标识了一个受 Spring 管理的组件

(2)@Respository:标识持久层组件

(3)@Service:标识服务层组件

(4)@Controller :标识表现层组件

3.对于扫描到的组件,Spring 有默认的命名策略:使用简短类名,第一个字母小写。也可以通过 value 属性指定名称。

4.当在组件类上使用了特定注解后,还需要在 Spring 的配置文件中声明 <context:component-scan>。

属性:

base-package:指定要扫描的基类包,Spring会自动扫描这个基类包及其子包中的所有类。当需要扫描多个包是,可以使用逗号进行分割。

如:

<context:component-scan base-package="com.nucsoft.spring"/>

resource-pattern:若需要扫描基包下指定的类,可以使用该属性过滤特定的类。默认是:"**/*.class"。

如:

<context:component-scan base-package="com.nucsoft.spring" resource-pattern="component/*.class" />

<context:include-filter type="" expression=""/> 子节点表示要包含的目标类

<context:exclude-filter type="" expression=""/> 子节点表示要排出在外的目标类  

可以同时包含多个 <context:include-filter type="" expression=""/> 和 <context:exclude-filter type="" expression=""/> 子节点

属性 type:表示支持不同类型的过滤

annotation:所有标注某注解的类。该类型采用目标类是否标注了某注解进行过滤

e:所有在基包下标注 @Controller 注解的类都不被扫描

<context:component-scan base-package="com.nucsoft.spring">
  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

assinable:所有继承或扩展某个特定的类进行过滤

e:所有继承或扩展 Person 类的类都不被扫描

<context:component-scan base-package="com.nucsoft.spring" resource-pattern="component/*.class">
  <context:exclude-filter type="assignable" expression="com.nucsoft.spring.bean.Person"/>
</context:component-scan>

四、基于注解来装配 Bean 的属性

1.<context:component-scan> 还会自动注册 AutowiredAnnotationBeanPostProcessor 实例,该实例可以自动装配具有 @Autowired 和 @Resource、@Inject 注解的属性。

2.@Autowired 注解

自动装配目标 Bean 的 Bean 属性(该属性为一个 Bean 的实例,该 Bean 为在 IOC 容器中存在的 Bean)

(1)可以对属性标注该注解。如:

/**
* @author solverpeng
* @create 2016-07-19-16:49
*/
@Component
public class Department {
private String deptName; @Autowired
private Employee employee;
@Autowired
private Address address; public void setDeptName(String deptName) {
this.deptName = deptName;
} @Override
public String toString() {
return "Department{" +
"deptName='" + deptName + '\'' +
", employee=" + employee +
", address=" + address +
'}';
}
}

(2)可以对方法标注该注解,方法参数为要自动装配的类型,可以是任意方法

/**
* @author solverpeng
* @create 2016-07-19-16:49
*/
@Component
public class Department {
private String deptName;
private Employee employee;
private Address address; @Autowired
public void setAddress(Address address) {
this.address = address;
} @Autowired
public void abc(Employee employee) {
this.employee = employee;
} public void setDeptName(String deptName) {
this.deptName = deptName;
} @Override
public String toString() {
return "Department{" +
"deptName='" + deptName + '\'' +
", employee=" + employee +
", address=" + address +
'}';
}
}

(3)可以对构造器标注该注解,方法参数为要自动装配的类型。

/**
* @author solverpeng
* @create 2016-07-19-16:49
*/
@Component
public class Department {
private String deptName;
private Employee employee;
private Address address; public void setDeptName(String deptName) {
this.deptName = deptName;
} @Autowired
public Department(Employee employee, Address address) {
this.employee = employee;
this.address = address;
} @Override
public String toString() {
return "Department{" +
"deptName='" + deptName + '\'' +
", employee=" + employee +
", address=" + address +
'}';
}
}

注意:

使用 @Autowired 自动匹配时,如果只匹配到一个的情况下:

按照类型进行匹配

如果匹配到多个:

标记有 primary="true" 的 bean 有限,不能同时出现多个 primary="true" 的相同类型的 bean。否则:UnsatisfiedDependencyException

若都没有 primary 属性,在按照 @Autowired 标注的构造器或方法 的参数名称进行匹配 Bean。若还没有匹配到,则报:UnsatisfiedDependencyException异常。

具体参见:

org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates

org.springframework.beans.factory.support.DefaultListableBeanFactory#determinePrimaryCandidate

(4)若某一个属性允许不被设置,可以设置 @Autowired 注解的 required 属性为 false。

(5)@Qualifier 注解:Spring 允许对方法的入参或属性标注 @Qualifier 注解。@Qualifier 注解里提供 Bean 的名称。

如:

属性处:

@Autowired
@Qualifier("address2")
private Address address;

方法处:

@Autowired
public Department(Employee employee, @Qualifier("address2") Address address) {
  this.address = address;
  this.employee = employee;
}

(6)@Autowired 注解可以标识在数组类型的属性上,此时会把所有匹配的 Bean 进行自动装配

(7)@Autowired 注解可以标识在集合属性上,此时会将集合类型对应的 Bean 进行自动装配

(8)@Autowired 注解可以标识在 Map 上,若 key 为 String,则此时会将 value 对应的 Bean 的类型进行自动装配

 3.@Resource 注解

(1)如果说 @Autowired 属性是按照类型进行自动装配的,那么 @Resource 注解可以看成是按照名称进行装配的。

@Resource 注解要求提供一个 Bean 名称的属性,若该属性为空,则自动采用标注出的变量或方法名作为 Bean 的名称。

注意:不能标注于构造器。

4.@Inject 注解

和 @Autowire的 注解一样也是按照类型匹配注入的 Bean ,但是没有 required 属性。

5.最后,对比一下@Resource和@Autowired

(1)@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入

(2)@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用

(3)@Resource注解是又J2EE提供,而@Autowired是由spring提供,故若要减少系统对spring的依赖建议使用 @Resource的方式;

6.最最后,推荐使用 @Autowired 注解。

Spring基础——在Spring Config 文件中配置 Bean的更多相关文章

  1. web.config文件中配置数据库连接的两种方式

    web.config文件中配置数据库连接的两种方式 标签: 数据库webconfig 2015-04-28 18:18 31590人阅读 评论(1)收藏举报    分类: 数据库(74)  在网站开发 ...

  2. 如何在web.config文件中配置Session变量的生命周期

    实例说明:在网上购物商城中,为了维护在线购物环境,一般只有注册会员才可以购买商品.实现购物功能时,先通过Session变量记录会员的登录名,然后在购买商品页面通过判断会员是否登录确定其能否购买商品. ...

  3. Spring基础15——通过工厂方法来配置bean

    1.什么是工厂方法 这里的工厂方法指的是创建指定bean的方法.工厂方法又分为静态工厂方法和实例工厂方法. 2.静态工厂方法配置bean 调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中 ...

  4. Spring 在xml文件中配置Bean

    Spring容器是一个大工厂,负责创建.管理所有的Bean. Spring容器支持2种格式的配置文件:xml文件.properties文件,最常用的是xml文件. Bean在xml文件中的配置 < ...

  5. Spring基础—— 在 Spring Config 中使用外部属性文件

    一.在 Spring Config 文件中配置 Bean 时,有时候需要在 Bean 的配置里添加 系统部署的细节信息, 如文件路径,数据源配置信息.而这些部署细节实际上需要在配置文件外部来定义. 二 ...

  6. c# 如何使用DLL的config文件中的信息

    我知道用c#编写的exe程序可以读取config文件中的配置信息,比如Test.exe,可以在与Test.exe相同目录下放置一个config文件:Test.exe.config,用System.Co ...

  7. Spring MVC框架下在java代码中访问applicationContext.xml文件中配置的文件(可以用于读取配置文件内容)

    <bean id="propertyConfigurer" class="com.****.framework.core.SpringPropertiesUtil& ...

  8. 修改和获取web.config或app.config文件appSettings配置节中的Add里的value属性 函数

    1: /// <summary> 2: /// 修改web.config或app.config文件appSettings配置节中的Add里的value属性 3: /// </summ ...

  9. IOC注入框架——Unity中Web.Config文件的配置与调用

    Unity 应用程序块可以从 XML 配置文件中读取配置信息.配置文件可以是 Windows Forms 应用程序的 App.config 或者 ASP.NET 应用程序的 Web.config.当然 ...

随机推荐

  1. Ubuntu server下搭建Maven私服Nexus

    Ubuntu server下搭建Maven私服Nexus Maven私服Nexus的作用,主要是为了节省资源,在内部作为maven开发资源共享服务器来使用. 1.下载 通过root用户进去Ubuntu ...

  2. Windows 2008 利用Filezilla server搭建FTP

    Windows 2008 利用Filezilla server搭建FTP, 安装后总是提示Error Connection To Server Lost , 后来,无意中先安装了IIS,再安装file ...

  3. ADT公司G729 方案指标

    ADT公司G729 方案指标 G.729 Voice Compression Algorithm and its many annexes G.729 is used in wireless voic ...

  4. Golang pprof heap profile is empty

    Q: When you use `go tool pprof` get heap data, profile is empty. A: The default sampling rate is 1 s ...

  5. Fix “Windows cannot access the specified device path or file” Error

    http://helpdeskgeek.com/help-desk/windows-cannot-access-the-specified-device-path-or-file/ Method 1 ...

  6. jade模板引擎学习笔记(WebsStorm9.0.3+ nodejs+express+jade)

    jade环境搭建 jade标签写法 jade注释 jade添加类名.id.属性 jade添加脚本,css jade变量 jade多行文本显示 jade流程代码:for,each,while jade流 ...

  7. 自动SPF生成工具

    到openspf网站去自动生成一下,地址是http://old.openspf.org/wizard.html.详细解释见下图关于spf的详细语法请看http://www.openspf.org/SP ...

  8. delphi7的新生,参与分布式应用开发,调用RESTful API,Json的应用

    前言: 1.公司delphi7开发的传统软件还活得好好的,但是大家都知道delphi早已经日落西山了,现在成了后进.追随者.细细算了已经6.7不用了.新的delphixe7呢,没有时间成本去适应和研究 ...

  9. php 设计模式 - 单例

    概述: 作为对象的创建模式,单例确保某一个内在系统中只存在一个实例,它不可以创建副本. 克隆函数(__clone )以及构造函数(__construct )必须声明为私用, 防止外部程序 创建一个新类 ...

  10. PHP 常见语法 集合

    1.die()与exit()的真正区别 die 为 exit 的别名, 执行过程 将释放内存,停止代码执行 echo "begin exec <br/>"; show( ...