简介
spring中将java对象称为bean,装配bean的三种方式
- 隐式的bean发现机制和自动装配(企业主流)
- 在java中进行显示的配置
- 在xml中进行显示的配置
1. 隐式的bean发现机制和自动装配
- 组建扫描
- @Component:表示这个类需在应用程序中被创建
- @ComponentScan:自动发现应用程序中创建的类
- 自动装配
- @Autowired:自动满足bean之间的依赖
- 定义配置类
- @Configuration:表示当前类是一个配置类
1.1创建项目
和之前一样
1.2使用配置类
当没有main方法时,如何测试?
创建配置类,将@componentscan与main方法解耦
package soundsystem;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;/***Spring程序配置类*/@ComponentScan@Configurationpublic class AppConfig {}
1.3使用junit4单元测试
普通创建模式
- pom.xml中添加依赖
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
2.在test中创建一个和java文件夹下一样的文件结构,并创建测试类
package soundsystem;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AppTest {
@Test
public void testPlay(){
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
CDPlayer player = context.getBean(CDPlayer.class);
player.play();
}
}
spring创建模式
- 引入Spring单元测试mokuai
- maven : junit、spring-test
- @RunWith(SpringJUnit4ClassRunner.class)
- 加载配置类
- ContextConfiguration(classes = AppConfig.class)
pom.xml中加入依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.13.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>2.在test中创建一个和java文件夹下一样的文件结构,并创建测试类
package soundsystem;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class AppTest {
@Autowired
private CDPlayer player;
@Test
public void testPlay(){
player.play();
}
}
1.4Autowired使用场景
构造函数进行依赖注入(效率最高)
@Autowired public CDPlayer(CompactDisc cd, Power power) { this.cd = cd; this.power = power; System.out.println("CDPlayer的多参数构造函数。。。"); }成员变量进行依赖注入(最便捷的方式)
@Autowired private CompactDisc cd; @Autowired private Power power;set方法进行依赖注入
@Autowired public void setCd(CompactDisc cd) { this.cd = cd; System.out.println("调用setcd..."); } @Autowired public void setPower(Power power) { this.power = power; System.out.println("调用setPOWER..."); }在任意方法进行依赖注入
@Autowired public void prepare(CompactDisc cd,Power power){ this.cd = cd; this.power = power; System.out.println("prepare方法被调用。。。"); }
1.5 required
- @Autowired(required=false)
- 表示注入方式是可选的
1.6 使用接口
有两点注意:
- @Component写在实现类中,而不是接口
- 申请接口的成员变量
1.7 自动装配的歧义性
当有两个类实现了同一个接口的同一个方法时会产生歧义
package com.qfendu.demo.service.impl;
import com.qfendu.demo.service.UserService;
import org.springframework.stereotype.Component;
@Component
public class UserServiceNormal implements UserService {
public void add() {
System.out.println("添加用户");
}
}
package com.qfendu.demo.service.impl;
import com.qfendu.demo.service.UserService;
import org.springframework.stereotype.Component;
@Component
public class UserServiceFestival implements UserService {
public void add() {
System.out.println("注册用户并发送优惠劵");
}
}
package com.qfen.demo.service;
import com.qfendu.demo.service.AppConfig;
import com.qfendu.demo.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testAdd(){
userService.add();
}
}
有两种方法解决:
1.7.1.声明变量时用实现类声明(并不好,没有面向接口)
1.7.2使用首选been
将要使用的实现类添加一个注解Primary
package com.qfendu.demo.service.impl;
import com.qfendu.demo.service.UserService;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component
@Primary
public class UserServiceFestival implements UserService {
public void add() {
System.out.println("注册用户并发送优惠劵");
}
}
缺点:只能有一个首选bean,且是在实现类中添加的,后期不好更改
1.7.3使用限定符
1.7.3.1 在实现类中添加限定符注解@Qualifier(“ID”)
1.7.3.2 在测试类中的变量声明中添加限定符注解@Qualifier(“ID”)
package com.qfendu.demo.service.impl;
import com.qfendu.demo.service.UserService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
@Qualifier("normal")
public class UserServiceNormal implements UserService {
public void add() {
System.out.println("添加用户");
}
}
package com.qfendu.demo.service.impl;
import com.qfendu.demo.service.UserService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
@Qualifier("festival")
public class UserServiceFestival implements UserService {
public void add() {
System.out.println("注册用户并发送优惠劵");
}
}
package com.qfen.demo.service;
import com.qfendu.demo.service.AppConfig;
import com.qfendu.demo.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {
@Autowired
@Qualifier("normal")
private UserService userService;
@Test
public void testAdd(){
userService.add();
}
}
1.7.4使用限定符和类ID(二)
1.7.4.1在实现类中的@Component后面添加id
1.7.4.2在测试类中添加@Qualifier(“ID”)
package com.qfendu.demo.service.impl;
import com.qfendu.demo.service.UserService;
import org.springframework.stereotype.Component;
@Component("normal")
public class UserServiceNormal implements UserService {
public void add() {
System.out.println("添加用户");
}
}
package com.qfen.demo.service;
import com.qfendu.demo.service.AppConfig;
import com.qfendu.demo.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {
@Autowired
@Qualifier("normal")
private UserService userService;
@Test
public void testAdd(){
userService.add();
}
}
1.7.5使用限定符和类ID(三)
实现类什么都不做,测试类添加@Qualifier(“ID”)
spring会给实现类一个默认ID,就是第一个字母小的类名
package com.qfendu.demo.service.impl;
import com.qfendu.demo.service.UserService;
import org.springframework.stereotype.Component;
@Component
public class UserServiceNormal implements UserService {
public void add() {
System.out.println("添加用户");
}
}
package com.qfen.demo.service;
import com.qfendu.demo.service.AppConfig;
import com.qfendu.demo.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {
@Autowired
@Qualifier("userServiceNormal")
private UserService userService;
@Test
public void testAdd(){
userService.add();
}
}

1.7.6 java标准的解决方案(一)
测试类中给变量添加注解Resource(name = “ID”),不要Autowired
Resource(name = “ID”)相当于@Autowired加@Qualifier(“ID”),这个不是spring的标准中的内容,是jdk标准中的内容
package com.qfen.demo.service;
import com.qfendu.demo.service.AppConfig;
import com.qfendu.demo.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {
// @Autowired
// @Qualifier("userServiceNormal")
@Resource(name = "userServiceNormal")
private UserService userService;
@Test
public void testAdd(){
userService.add();
}
}
1.7.7 java标准的解决方案(二)
基本和1.7.5相同,@Resource也可以使用自定义ID
package com.qfendu.demo.service.impl;
import com.qfendu.demo.service.UserService;
import org.springframework.stereotype.Component;
@Component("ff")
public class UserServiceFestival implements UserService {
public void add() {
System.out.println("注册用户并发送优惠劵");
}
}
package com.qfen.demo.service;
import com.qfendu.demo.service.AppConfig;
import com.qfendu.demo.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {
// @Autowired
// @Qualifier("userServiceNormal")
@Resource(name = "ff")
private UserService userService;
@Test
public void testAdd(){
userService.add();
}
}
1.8 处理分层架构
用于区分个层的注解
web层 Controller
service层 Service
dao层 Repository
这三个都可以代替@Component,作用没有区别,只是语义上进行区别
1.9设置组件扫描的基础包
@ComponentScan
默认情况下只扫描本包(文件夹),添加路径可以扫描路径下所有的包
@ComponentScan("com.qfendu.demo")
使用basePackages,可以像数组一样添加多个包(有缺陷,修改包名后,这里也需要修改)
@ComponentScan(basePackages = {"com.qfendu.demo.web","com.qfendu.demo.dao"})
使用basePackageClasses,可以像数组一样添加多个类(比方法二更安全)
@ComponentScan(basePackageClasses = {UserController.class, UserService.class, UserDao.class})
1.10 使用xml启用组件扫描
新建一个applicationContext.xml文件,在里面添加路径
<?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.xsd">
<!--添加路径-->
<context:component-scan base-package="com.qfendu.demo"/>
</beans>
1.11 总结

