注意:IOC使用注解创建对象,默认走的无参构造方法。但有种特殊的情况,当依赖注入DI使用@Autowired +@Qualifier()的方式,且又使用构造方式注入时,当这个类中,既有无参构造方法,又有有参的构造方法(一个时),这时候的创建对象还是调用的无参构造方法;但倘若将无参构造方法去掉,这时候的创建对象就只会调有参的构造方法,该有参构造方法的请求参数类型必须是spring容器中有的对象,这时候spring就会将spring容器的对应对象注入到该参数中;其他情况会报异常。总结就是:反正要不就只有一个无参构造器,要不就只有一个带有需要注入的有参构造方法。

配置步骤

第一步:拷贝必备jar包到工程的lib目录

注意:在基于注解的配置中,我们还要多拷贝一个aop的jar包。如下图:

spring 使用构造函数注入参数过多 spring有参构造方法注入注解_spring

第二步:在类的根路径下创建一个任意名称的xml文件(不能是中文)

–项目结构图

spring 使用构造函数注入参数过多 spring有参构造方法注入注解_xml_02

注意:基于注解整合时,Spring配置文件导入约束时需要多导入一个context名称空间下的约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
    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
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
">
</beans>

第三步:创建一个服务类

package com.spring.service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/*
 * 	@Component(value="service")
 * 	value="设置当前bean的名称"。不设置的话,则默认为类名首字母小写。当前场景为:customService
 * 	Spring IOC注解
 * 	Spring框架在启动的时候,会去扫描对应的包,判断包下面的类上面是否贴有@Componet注解,
 * 	如果有,Spring认为这个类归我管理,认为这个类需要创建对象
 * 
 * 	--------------------------------------------------------------------
 * 	@Scope
 * 	设置bean作用范围
 * 	value:设置作用范围
 * 		值:singleton:单例 。默认为单例
 *  	   prototype:多例
 *  	   request:一次请求-web项目
 *  	   session:一次会话-web项目
 *  ---------------------------------------------------------------------
 *  @PostConstruct //该注解相当于<bean init-menthod="init"/>
	//@PostConstruct是java官方的,不是spring的
	---------------------------------------------------------------------
	@PreDestroy //该注解相当于<bean destory-method="destory"/>
	//@PreDestroy是java官方的,不是spring的
 */
@Component
@Scope
public class CustomService {

	public CustomService() {
		super();
		System.out.println("无参构造方法");
	}
	
	public void say() {
		System.out.println("Hello World");
	}
	
	@PostConstruct //该注解相当于<bean init-menthod="init"/>
	//@PostConstruct是java官方的,不是spring的
	public void init() {
		System.out.println("初始化方法");
	}
	
	@PreDestroy //该注解相当于<bean destory-method="destory"/>
	//@PreDestroy是java官方的,不是spring的
	public void destory() {
		System.out.println("销毁方法");
	}

}

第四步:在spring的配置文件加入扫描注解

<?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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        
        <!-- 声明扫描包以及子包的类。如果发现有组件注解的类,就创建对象,并加入到容器
        	配置Spring注解包扫描的位置
        	<context:component-scan base-package="com.spring"/>
        	base-package:对应要扫描包的位置,可以扫描多个包,使用逗号隔开
         -->
         <context:component-scan base-package="com.spring"/>
</beans>

第五步:测试调用代码

@Test
	public void testName() throws Exception {

		// 1.读取Spring配置文件,启动Spring框架,创建Spring容器对象
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

		CustomService customService = applicationContext.getBean("customService", CustomService.class);
		customService.say();

	}

第六步:测试结果

spring 使用构造函数注入参数过多 spring有参构造方法注入注解_xml_03

用于创建对象的注解-IOC相关注解

1、组件注解@Component之类

我们将用于被扫描创建对象的注解,统称为组件注解。

组件包括:@Component,@Controller,@Service,@Repository。

组件注解的功能都是标识类为注解的组件类,启动Spring框架的程序时,声明将这些组件类注入到Spring容器里面。意味着,只有加了这四个注解任何一个注解的类,在程序启动的时候,Spring就通过配置文件指定的路径将该路径下的所有带组件注解的类创建对象并且放在容器里面。

功能类似原来配置文件的标签

问题:明明一个@Component注解就可以满足了扫描的需要,为什么要有四个呢?
答:其实Spring第一版注解的实现(spring 2.5),就是使用一个@Component。从3.0以后,作者认为根据分层的需要,把它拆成了四个。为了可以让开发人员,可见即可得,一看到注解,立即知道类的性质。所以分成了四个

@Controller:用于声明表示层的组件注解
@Service:用于声明服务层的组件注解
@Repository:用于声明持久层的组件注解
@Component:用于声明三层以外的组件注解

问题:那么,这四个注解交换使用会报错吗。如:持久层,我放@Service标记。
答:处理@Controller在SpringMVC里面有强制的要求,SpringMVC的表示层必须使用@Controller组件注解。其他情况,用乱了是不会报错的,不过我们必须不能用乱。不遵守规范,不然别人无法跟你一起开发了。

2、@Scope用于设置对象的生命周期注解

Xml配置需要配置对象的作用范围

<bean id="someBean" class="..."  scope="作用范围"></bean>

如果使用注解配置bean,那么bean的作用范围也需要使用注解配置。该注解为:@Scope(“作用范围”)。取值范围如下图所示:

spring 使用构造函数注入参数过多 spring有参构造方法注入注解_构造方法_04

在开发中主要使用 scope=“singleton”、 scope=“prototype”
对于MVC中的Action/Controller使用prototype类型,其他使用singleton

3、@PostConstruct @PreDestroy初始化和销毁方法注解

在xml配置中可以配置对象的初始化方法和销毁方法

<bean id="someBean" class="cn.zj.spring.domain.SomeBean" 
		init-method="init"
		destroy-method="destory"></bean>

如果使用注解配置bean,那么bean的作用范围也需要使用注解配置

@PostConstruct // 相当于<bean init-method="init" />
public void init() {
	System.out.println("初始化方法执行了");
}
@PreDestroy// 相当于<bean destroy-method="destory" />
public void destory() {
	System.out.println("销毁方法执行了");
}