spring 学习笔记

参考spring5.1.9文档编写
官网:https://spring.io/projects/spring-framework
Spring概述
spring是什么
Spring是一个轻量级开源框架,是为了解决企业应用开发的复杂性而创建的。Spring 用于整合,好处是解耦。解耦,可以降低组件与组件之间的关联,改善程序结构,便于系统的维护和扩展。
以IOC(控制反转)和AOP(切面编程)为内核。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
一般而言,使用 Spring 框架的主要作用:我们会使用 IoC 整合组件(各种 Bean),使用 AOP 来管理事务。Spring 的使用没有限制,用于 Web 工程还是普通 Java 程序都可以。
JavaEE规范的三层结构体系:
 表现层(页面数据显示、页面跳转调度)jsp/servlet
 业务层(业务处理和功能逻辑、事务控制)-service
 持久层(数据存取和封装、和数据库打交道)dao

Spring特性
 IOC(Inversion of Control):即创建被调用的实例不是由调用者完成,而是由Spring容器完成,并注入调用者。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。
 AOP(Aspect-Oriented Programming):面向切面编程
 容器:spring作为一个容器,包含并管理应用对象的声明周期,对象和对象之间的依赖关系。
 轻量:减少开发的复杂度。spring是非侵入性的,基于spring开发的应用中的对象可以不依赖于spring中的api.
 一站式:Spring提供了JavaEE各层的解决方案,表现层:Spring MVC,持久层:JdbcTemplate、ORM框架整合,业务层:IoC、AOP、事务控制。在AOP和IOC的基础上,可以整合各个企业应用的开源框架和优秀的第三方类库。

Spring模块
七大核心模块:

核心容器(Spring Core)
核心容器提供Spring框架的基本功能。定义了创建、 配置、和管理bean的方式。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。
应用上下文(Spring Context)
  Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring面向切面编程(Spring AOP)
  通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring框架中。所以,可以很容易地使 Spring框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
JDBC和DAO模块(Spring DAO)
  JDBC、DAO的抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。
对象实体映射(Spring ORM)
  Spring框架插入了若干个ORM框架,从而提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有这些都遵从Spring的通用事物和DAO异常层次结构。
Web模块(Spring Web)
  Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。所以Spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
MVC模块(Spring Web MVC)
  MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。MVC容纳了大量视图技术,其中包括JSP、POI等,模型来有JavaBean来构成,存放于m当中,而视图是一个接口,负责实现模型,控制器表示逻辑代码,由c的事情。Spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境。Spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问的对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用。

第一个spring程序
spring相关的jar下载地址:https://repo.spring.io

新建工程
创建工程spring01,并添加spring核心jar包,spring框架所需日志包的依赖:

新建接口UserService
publicinterface UserService {
publicvoid add();
}

新建实现类UserServiceImpl
publicclass UserServiceImpl implements UserService{

@Override
publicvoid add() {
	System.out.println("add User..");
}

}

新建测试类
不使用spring的方式
publicstaticvoid main(String[] args) {
//常规使用方法,注意此种写法并没有使用到spring
UserService userService = new UserServiceImpl();
userService.add();
}

使用spring
新建applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<bean id="userService" class="com.niit.service.impl.UserServiceImpl"></bean>

新建测试类
publicstaticvoid main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(“applicationContext.xml”);
UserService userService = (UserService) classPathXmlApplicationContext.getBean(“userService”);//这个名字需要和xml中的名字一致
userService.add();
}

IOC(Inversion of Control)控制反转
其思想是反转资源获取的方向。容器会主动的将资源推送给他所管理的组件,组件要做的是选择一种合适的方式来接收资源。
在类和类之间存在控制权, 控制权指的是对象的创建和使用,比如有类 A 和类 B,我们之前的做法是在 A 中调用 B,那么控制权就在 A 中,这样做的耦合度较高,如果修改了 B, A 也要做相应修改。
引入 Spring 框架后,控制权由 spring 容器来负责。当 A 想使用 B 时,需要由 Spirng 容器通过配置文件进行注入。这种思想就是 IoC(为了更好的理解,我们可以这样认为,对象创建和使用的控制权转移到了 Spring 容器,由 Spring 容器来控制)。

spring提供了两种类型的IOC容器实现:
 BeanFactory:IOC容器的基本实现,面向spring本身。参见使用beanfactory实现
 ApplicationContext:提供了更多高级的性能,是BeanFactory的子类,面向开发者。参见使用ApplicationContext实现

配置bean
基于XML配置方式
在xml中通过使用节点配置bean,示例如下:

<beanid="userService"class="com.niit.service.impl.UserServiceImpl"></bean>

属性
id: bean的唯一标识
class:指定全类名,以反射的方式创建对象
name:别名
Scope:范围,简单的可以理解成对象在IOC中的生命周期。可选值有六个,参见Scopes。
Constructorarguments:构造器参数
Properties:属性
Autowiringmode:自动装配模式
Lazyinitializationmode:懒加载模式
Initializationmethod:初始化方法:
Destructionmethod:销毁模式

示例:

  1. 创建类HelloWord.java
    publicclass HelloWorld {
    private String name ;

    publicString getName() {
    returnname;
    }

    publicvoid setName(String name) {
    this.name = name;
    }

    publicvoid sayHello() {
    System.out.println("hello: " + name);
    }
    }

  2. 修改applicationContext.xml
    <beanid=“helloWord” class=“com.niit.entity.HelloWorld”>
    <propertyname="name"value=“zs”>

  3. 测试类
    方式一(不推荐):使用beanFactory实现
    import org.springframework.beans.factory.BeanFactory;
    importorg.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;

import com.niit.entity.HelloWorld;

publicstaticvoid main(String[] args) {
	Resource resource = new ClassPathResource("applicationContext.xml");
	BeanFactory xmlBeanFactory = newXmlBeanFactory(resource);//
	HelloWorld hw = (HelloWorld) xmlBeanFactory.getBean("helloWord");
	hw.sayHello();
}

方式二(推荐):使用ApplicationContext实现
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.niit.entity.HelloWorld;

publicstaticvoid main(String[] args) {
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(“applicationContext.xml”);

	HelloWorld hw = (HelloWorld)classPathXmlApplicationContext.getBean("helloWord");
	hw.sayHello();

}

基于注解方式
组件扫描:spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件。
特定的组件有:

  1. 扫描 Bean 组件的注解,替代 xml 中的元素的定义
     @Component:组件,受spring管理。
     @Respository:持久层组件
     @Service:业务层组件
     @Controller: 表现层组件
    对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写。也可以在注解中通过value属性标识组件的名称。

注意:需要加入aop的包(spring-aop-5.1.9.RELEASE.jar),否则会报错。

  1. 依赖注入的注解标记
     @Resource JDK 提供的。先按类型,后按名称来自劢装配
     @AutoWired Spring 提供的,先按名称,后按类型来自劢装配
     @Qualifier(“id 名”)

  2. 其他注解
      @Scope 等价于
      @PostConstruct 等价于
      @PreDestroy 等价于

示例
项目结构如下:

  1. 新建UserController.java, UserService.java, UserDao.java

1)UserController.java
import org.springframework.stereotype.Controller;

@Controller
publicclass UserController {

}

2)UserService.java
import org.springframework.stereotype.Service;

@Service
publicclass UserService {

}

3)UserDao.java
@Repository
publicclass UserDao {

}

  1. 新建applicationContext.xml

context:component-scanbase-package=“com.demo.spring”</context:component-scan>

  1. 测试
    publicstaticvoid main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext(“applicationContext.xml”);
    UserController uc = (UserController)ac.getBean(“userController”);
    System.out.println(uc);
    UserService us = (UserService)ac.getBean(“userService”);
    System.out.println(us);
    UserDao ud = (UserDao)ac.getBean(“userDao”);
    System.out.println(ud);
    }

  2. 结果

context:exclude-filter用法
context:exclude-filter表示自动扫描中需要排除的项。
例如:
context:component-scanbase-package=“com.niit.spring”

<context:exclude-filter type="annotation"expression=“org.springframework.stereotype.Repository”/>

<context:exclude-filter type="assignable"expression=“com.niit.spring.controller.UserController”/>
</context:component-scan>

<context:include-filter用法
<context: include-filter>表示自动扫描中需要包含的项。

context:component-scanbase-package="com.niit.spring"use-default-filters=“false”

context:include-filtertype="annotation"expression=“org.springframework.stereotype.Controller”/

	<context:include-filtertype="assignable"expression="com.niit.spring.controller.UserController"/>
</context:component-scan>

@Autowired 自动装配
使用@Autowired注解,可以自动装配bean
示例:

  1. UserService.java
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

import com.niit.spring.dao.UserDao;

@Service
publicclass UserService {

	@Autowired
	private UserDao userDao;
	
	publicvoid login() {
		userDao.findByName();
	}

}

UserDao.java
import org.springframework.stereotype.Repository;

@Repository
publicclass UserDao {
publicvoid findByName() {
System.out.println(“调用了 UserDao 的方法”);
}
}

  1. ApplicationContext.xml

context:component-scanbase-package=“com.niit.spring”
</context:component-scan>

  1. 测试
    publicstaticvoid main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext(“applicationContext.xml”);
    UserService us = (UserService)ac.getBean(“userService”);
    System.out.println(us);
    us.login();
    }

  2. 打印

多种类型都匹配的情况

  1. 新建以下类,一个dao有多个实现类,并在service中注入实现类。
    UserService.java
    @Service
    publicclass UserService {

    /**
     * @Autowired优先使用类型匹配的方式装配bean,如果有多个类型都能匹配,会使用变量名和bean的id匹配。
     * 		也可以使用@Qualifier 注解指定注入的bean
     */
    @Autowired()
    @Qualifier("userDaoImpl1")
    private UserDao userDaoImpl1;
    
    publicvoid login() {
    	userDaoImpl1.findByName();
    }
    

}

UserDao.java
publicinterface UserDao {
publicvoid findByName();

}

UserDaoImpl1.java
import org.springframework.stereotype.Repository;

@Repository
publicclass UserDaoImpl1 implements UserDao {

@Override
publicvoid findByName() {
	System.out.println("UserDaoImpl1 ");
}

}

UserDaoImpl2.java
import org.springframework.stereotype.Repository;

@Repository
publicclass UserDaoImpl2 implements UserDao {

@Override
publicvoid findByName() {
	// TODO Auto-generated method stub
	System.out.println("UserDaoImpl2");
}

}

  1. 测试

    publicstaticvoid main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext(“applicationContext.xml”);
    UserService us = (UserService)ac.getBean(“userService”);
    System.out.println(us);
    us.login();
    }

基于Java的配置
无需编写xml
示例

  1. 新建Appconfig.java类
    importorg.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

import com.niit.spring.service.UserService;

/**

  • @Configuration用于定义配置类,可以替换xml配置文件。

*/
@Configuration
publicclass AppConfig {

/**
 * @bean注册bean对象
 * 		相当于在xml中的:<bean id="myUserService" class="com.niit.spring.service.UserService"></bean>
 * @return
 */
@Bean
public UserService myUserService() {
	returnnew UserService();
}

}

UserService.java
@Service
publicclass UserService {

	publicvoid login() {
		//….
	}

}

  1. 测试
    注意:此处需要使用的是AnnotationConfigApplicationContext类。
    publicstaticvoid main(String[] args) {
    ApplicationContext ac = newAnnotationConfigApplicationContext(AppConfig.class);
    UserService userService = (UserService)ac.getBean(“myUserService”);
    System.out.println(userService);
    }

  2. 结果

配置自动扫描
配置方式也可以使用自动扫描,使用@ComponentScan注解。

  1. AppConfig.java

/**

  • @Configuration用于定义配置类,可以替换xml配置文件。

*@ComponentScan(“com.niit.spring”) 相当于:
*<context:component-scan base-package=“com.niit.spring”>
</context:component-scan>
*/
@Configuration
@ComponentScan(“com.niit.spring”)
//@ComponentScan(basePackages=“com.niit.spring”)//也可以写成这样
publicclass AppConfig {

/**
 * @bean注册bean对象
 * 		相当于在xml中的:<bean id="myUserService" class="com.niit.spring.service.UserService"></bean>
 * @return
 */

// @Bean
// @Scope(“prototype”)
// public UserService myUserService() {
// return new UserService();
// }
}

@ComponentScan
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

/**

  • @Configuration用于定义配置类,可以替换xml配置文件。

*@ComponentScan(“com.niit.spring”) 相当于:

  • <context:component-scan base-package=“com.niit.spring”>
    </context:component-scan>

    @ComponentScan(basePackages=“com.niit.spring”,
    includeFilters=@Filter(Service.class),useDefaultFilters=false)作用相当于:
    <context:component-scan base-package=“com.niit.spring” use-default-filters=“false”>

    <context:include-filter type=“annotation” expression=“org.springframework.stereotype.Controller”/>
    </context:component-scan>

    @ComponentScan(basePackages=“com.niit.spring”,excludeFilters=@Filter(Service.class))作用相当于:
    <context:component-scan base-package=“com.niit.spring” use-default-filters=“false”>
    <context:exclude-filter type=“annotation” expression=“org.springframework.stereotype.Service”/>
    </context:component-scan>
    */
    @Configuration
    @ComponentScan(basePackages=“com.niit.spring”,excludeFilters=@Filter(Service.class))
    publicclass AppConfig {

    /**

    • @bean注册bean对象
    •  相当于在xml中的:<bean id="myUserService" class="com.niit.spring.service.UserService"></bean>
      
    • @return
      */
      // @Bean
      // @Scope(“prototype”)
      // public UserService myUserService() {
      // return new UserService();
      // }
      }

spring容器对bean的管理
bean对象是什么时候被创建的
测试代码
 创建一个User类,增加构造器
publicclass User {

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

}

 在applicationContext.xml中配置

<?xml version="1.0" encoding="UTF-8"?>

<bean class="com.demo.User" id="user">
</bean>

 测试类
publicstaticvoid main(String[] args) {

//只加载xml文件创建spring容器实例
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
}

运行这个方法,控制台打印:

控制台打印结果显示,默认情况下 User 在 Spring 容器被创建时就会被创建。

修改对象的创建时机
使用lazy-init=true可以改变spring容器创建对象的时机。

单个bean

<?xml version="1.0" encoding="UTF-8"?>

<bean class="com.demo.User" id="user"lazy-init="true">
</bean>

运行上面的测试代码,会发现什么都不会打印,只有在使用User的时候,才会去创建User对象。
publicstaticvoid main(String[] args) {

//只加载xml文件创建spring容器实例,
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
User u = (User) context.getBean(“user”);
u.play();
}

控制台打印:

配置所有的bean都延迟创建

<?xml version="1.0" encoding="UTF-8"?>

bean对象的创建模式
bean 对象的创建模式是什么,是单例模式创建 Bean 对象还是每次创建都是新的?

测试代码
 User类
publicclass User {

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

}

 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<bean class="com.demo.User" id="user">
</bean>

 测试类
创建 2 个 User对象,通过对比,如果为 true,则表明是单例模式;如果为 false,则表明每次都创建新的 User 对象
publicstaticvoid main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
User u = (User) context.getBean(“user”);
User u1 = (User) context.getBean(“user”);
System.out.println(u == u1);//返回true
}

运行结果:

通过运行结果,我们可以看得出, Spring 容器是通过单例模式创建 Bean 对象的,也就是说,默认情况下,通过调用context.getBean(“user”)方法获得的对象都是同一个 user对象。

修改容器创建对象的模式
使用scope=”prototype”,设置bean的模式为原型模式即可。

<?xml version="1.0" encoding="UTF-8"?>

<bean class="com.demo.User" id="user"scope="prototype">
</bean>

运行测试代码:
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
User u = (User) context.getBean(“user”);
User u1 = (User) context.getBean(“user”);
System.out.println(u == u1);

控制台打印:

此时会发现创建了两个对象。

scope取值
在元素的scope属性里设置bean的作用域,共支持六个范围,其中四个只有在web环境下的applicationContext才可以使用。
Scope的可选范围如下:

request 表示 bean 对象生命周期和 request 生命周期相同
session 同 session
global session 相当于 application
single
prototype

依赖注入
DI(Dependency Injection):
依赖注入,IOC的另一种表达方式。即组件以一些预定好的方式(如setter方法)接受来自如容器的资源注入。相对IOC而言,这种表述更直接。
在springIOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化,只有在容器实例化后,才可以从IOC容器中获取bean实例并使用。

共有两种方式
 属性注入(set方法)
 构造器注入

注入类型有如下几种: 简单值、集合、 bean 对象。

Ioc 和 DI 的关系?
我们认为 Spring 是具有 IoC 特性的框架。
实现 IoC 是由 Spring 容器来完成的, Spring 容器通过依赖注入 DI 建立起对象(组件、 Bean)之间的关系。
我们可以这样理解: DI 是 IoC 实现的一种手段, Ioc 通过 DI 来实现。

属性注入(set方法)
属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。
属性注入要求:
 Bean提供一个默认的构造函数
 为需要注入的属性提供对应的Setter方法。
Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。

示例:
设置简单值

  1. 创建Book类,并添加set方法
    package com.niit.entity;

publicclass Book {
private String name;//书名
privatedoubleprice;//价格
private String publisher;//出版商

//添加get/set方法toString()方法
…

}

  1. 修改applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>

<!-- 设置value的两种方法 -->
<bean id="book" class="com.niit.entity.Book">
	<property name="name" value="布瓜的世界"></property>
	<property name="price" value="24.5"></property>
	<property name="publisher" value="海豚出版社"></property>
</bean>
  1. 测试
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.niit.entity.Book;

publicclass TestSpring {

publicstaticvoid main(String[] args) {

	ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	Book book = (Book) classPathXmlApplicationContext.getBean("book");
	System.out.println(book);		
	
}

}

结果:打印输出:

引用其他的bean
在配置文件中,可以使用元素或ref属性为bean的属性或构造器参数指定对bean的引用。也可以在属性或构造器里包含bean的声明,这样的bean称为内部bean。

  1. 新建Student.java
    publicclass Student {
    private String sname;// 学生姓名
    private Book book;// 拥有的书籍

    //get/set…方法
    //toString()方法
    

    }

  2. 修改applicationContext.xml
    <beanid=“book” class=“com.niit.entity.Book”>



    <beanid="student"class=“com.niit.entity.Student”>
    <propertyname="sname"value=“张三”>
    <!—第一种写法:使用ref属性 -->
    <propertyname="book"ref=“book”><!—使用ref属性引用id=”book”的bean–>
    <!—第二种写法:使用元素 -->
    <propertyname=“book”>
    <refbean=“book”/>

    <!-- 第三种写法:内部bean,它声明在<property>或<constructor-arg>内部,不需要设置id或name属性。只能供内部使用,不能使用在其他任何地方 -->
    <propertyname="book">
    	<beanclass="com.niit.entity.Book">
    	<property name="name" value="布瓜的世界"></property>
    <property name="price" value="24.5"></property>
    <property name="publisher" value="海豚出版社"></property>
    	</bean>
    </property>
    
  3. 测试
    ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
    Student student = (Student) context.getBean(“student”);
    System.out.println(student);

结果打印:

设置级联值
使用上面的Student.java
<beanid=“student” class=“com.niit.entity.Student”>
<propertyname="sname"value=“张三”>
<propertyname="book"ref=“book”><!—注意此处需要先初始化,才能级联赋值,否则会有异常。–>
<property name="book.name"value=“星空”>

构造器注入
构造函数注入是除属性注入之外的另一种常用的注入方式,它保证一些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使用。
使用方式:

  1. 在类中,不用为属性设置setter方法,但是需要生成该类带参的构造方法。
  2. 在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到了节点,该节点有四个属性:
    · index:索引,指定注入的属性,从0开始;
    · name: 构造器参数名
    · type是指该属性所对应的类型;
    · ref 是指引用的依赖对象;
    · value 当注入的不是依赖对象,而是基本数据类型时,就用value;

示例
新建类Book.java
publicclass Book {
private String name;//书名
privatedoubleprice;//价格
private String publisher;//出版商

//添加有参构造器
public Book(String name, doubleprice, String publisher) {
	super();
	this.name = name;
	this.price = price;
	this.publisher = publisher;
}}

//重写toString()方法…

}

修改applicationContext.xml
1)第一种写法:默认

<beanid="book"class="com.niit.entity.Book">
	<constructor-argvalue="向左走向右走"></constructor-arg>
	<constructor-argvalue="12.5"></constructor-arg>
	<constructor-argvalue="海豚出版社"></constructor-arg>
</bean>

注:想要给属性设置null值,需使用标签。
如:

2)第二种写法:使用索引index

<beanid="book"class="com.niit.entity.Book">
	<constructor-argvalue="向左走向右走"></constructor-arg><!-- 此处index不写,默认为0  -->
	<constructor-argvalue="海豚出版社"index="2"></constructor-arg>
	<constructor-argvalue="12.5"index="1"></constructor-arg>
</bean>

3)第三种写法:使用类型type匹配

<beanid="book"class="com.niit.entity.Book">
	<constructor-argvalue="向左走向右走"></constructor-arg>
	<constructor-argvalue="海豚出版社"type="String"></constructor-arg>
	<constructor-argvalue="12" type="double"></constructor-arg>
</bean>

4)第四种写法:使用name匹配

<beanid="book"class=“com.niit.entity.Book”>
<constructor-argvalue=“向左走向右走”>
<constructor-argvalue="海豚出版社"name=“publisher”>
<constructor-arg name="num"value=“15”>

注意:使用name匹配,为了保证开箱即用,需开启调试模式。如果不能或不想使用调试编译代码,则需要在构造器上加入@ConstructorProperties注解。
@ConstructorProperties({“name”, “num”,“publisher”})
public Book(String name, intnum, String publisher) {
super();
this.name = name;
this.publisher = publisher;
this.num = num;
}

5)第五种写法:联合使用type和index
示例:
背景:

  1. 修改Book.java
    publicclass Book {
    private String name;//书名
    privatedoubleprice;//价格
    private String publisher;//出版商
    //增加图书数量
    private int num;//数量

    //增加包含图书数量的构造器,并将这个包含int类型的构造器,放在包含double构造器之前
    public Book(String name, int num, String publisher) {
    super();
    this.name = name;
    this.publisher = publisher;
    this.num = num;
    }

    public Book(String name, doubleprice, String publisher) {
    super();
    this.name = name;
    this.price = price;
    this.publisher = publisher;
    }

    @Override
    public String toString() {
    return"Book [name=" + name + “, price=” + price + “, publisher=” + publisher + “, num=” + num + “]”;
    }

}

  1. 修改applicationContext.xml
    此时如果修改为以下代码,则会输出不正确的数据(错误示范):
    <beanid=“book” class=“com.niit.entity.Book”>
    <constructor-argvalue=“向左走向右走”>
    <constructor-argvalue=“海豚出版社” index=“2”>
    <constructor-argvalue=“12” index=“1”><!—此处的12是价格 -->

    原因:构造器的第二个参数设置的值为12,可以是int,也可以是double,此时spring注入参数时,首先加载到第一个构造器,所以会将12作为数量输出,所以就产生了不正确的数据,打印数据如下:

解决方案:同时使用index和type
修改applicationContext.xml,给第二个参数增加type属性限定入参类型。
<beanid=“book” class=“com.niit.entity.Book”>
<constructor-argvalue=“向左走向右走”>
<constructor-argvalue=“海豚出版社” index=“2”>
<constructor-argvalue=“12” index=“1” type=“double”>

  1. 结果打印(测试代码在下面):

测试代码
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.niit.entity.Book;

publicclass TestSpring {

publicstaticvoid main(String[] args) {
	ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	Book book = (Book) classPathXmlApplicationContext.getBean("book");
	System.out.println(book);
}

}

目录 第一部分spring的核心 第1章开始spring之旅 1.1spring是什么 1.2开始spring之旅 1.3理解依赖注入 1.3.1依赖注入 1.3.2di应用 1.3.3企业级应用中的依赖注入 1.4应用aop 1.4.1aop介绍 1.4.2aop使用 1.5小结 第2章基本bean装配 2.1容纳你的bean 2.1.1beanfactory介绍 2.1.2使用应用上下文 2.1.3bean的生命 2.2创建bean 2.2.1声明一个简单的bean 2.2.2通过构造函数注入 2.3注入bean属性 2.3.1注入简单的数值 2.3.2使用其他的bean 2.3.3装配集合 2.3.4装配空值 2.4自动装配 2.4.1四种自动装配类型 2.4.2混合使用自动和手动装配 2.4.3何时采用自动装配 2.5控制bean创建 2.5.1bean范围化 2.5.2利用工厂方法来创建bean 2.5.3初始化和销毁bean 2.6小结 第3章高级bean装配 3.1声明父bean和子bean 3.1.1抽象基bean类型 3.1.2抽象共同属性 3.2方法注入 3.2.1基本的方法替换 3.2.2获取器注入 3.3注入非springbean 3.4注册自定义属性编辑器 3.5使用spring的特殊bean 3.5.1后处理bean 3.5.2bean工厂的后处理 3.5.3配置属性的外在化 3.5.4提取文本消息 3.5.5程序事件的解耦 3.5.6让bean了解容器 3.6脚本化的bean 3.6.1给椰子上lime 3.6.2脚本化bean 3.6.3注入脚本化bean的属性 3.6.4刷新脚本化bean 3.6.5编写内嵌的脚本化bean 3.7小结 第4章通知bean 4.1aop简介 4.1.1定义aop术语 4.1.2spring对aop的支持 4.2创建典型的spring切面 4.2.1创建通知 4.2.2定义切点和通知者 4.2.3使用proxyfactorybean 4.3自动代理 4.3.1为spring切面创建自动代理 4.3.2自动代理@aspectj切面 4.4定义纯粹的pojo切面 4.5注入aspectj切面 4.6小结 第二部分企业spring 第5章使用数据库 5.1spring的数据访问哲学 5.1.1了解spring数据访问的异常体系 5.1.2数据访问的模板化 5.1.3使用dao支持类 5.2配置数据源 5.2.1使用jndi数据源 5.2.2使用数据源连接池 5.2.3基于jdbc驱动的数据源 5.3在spring里使用jdbc 5.3.1处理失控的jdbc代码 5.3.2使用jdbc模板 5.3.3使用spring对jdbc的dao支持类 5.4在spring里集成hibernate 5.4.1选择hibernate的版本 5.4.2使用hibernate模板 5.4.3建立基于hibernate的dao 5.4.4使用hibernate3上下文会话 5.5springjava持久api 5.5.1使用jpa模板 5.5.2创建一个实体管理器工厂 5.5.3建立使用jpa的dao 5.6spring和ibatis 5.6.1配置ibatis客户模板 5.6.2建立基于ibatis的dao 5.7缓存 5.7.1配置缓存方案 5.7.2缓存的代理bean 5.7.3注解驱动的缓存 5.8小结 第6章事务管理 6.1理解事务 6.1.1仅用4个词解释事务 6.1.2理解spring对事务管理的支持 6.2选择事务管理器 6.2.1jdbc事务 6.2.2hibernate事务 6.2.3jpa事务 6.2.4jdo事务 6.2.5jta事务 6.3在spring中编写事务 6.4声明式事务 6.4.1定义事务参数 6.4.2代理事务 6.4.3在spring2.0里声明事务 6.4.4定义注释驱动事务 6.5小结 第7章保护spring 7.1springsecurity介绍 7.2验证用户身份 7.2.1配置providermanager 7.2.2根据数据库验证身份 7.2.3根据ldap仓库进行身份验证 7.3控制访问 7.3.1访问决策投票 7.3.2决定如何投票 7.3.3处理投票弃权 7.4保护web应用程序 7.4.1代理springsecurity的过滤器 7.4.2处理安全上下文 7.4.3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值