三种方式:
- 隐式的bean发现机制和自动装配(常用)
- 在java中进行显示的配置
- 在xml中进行显示的配置
创建项目
实现音响系统,CdPlayer,CompactDisc
package soundsystem; import org.springframework.stereotype.Component; @Component public class CompactDisc { public CompactDisc() { super(); System.out.println("CompactDisc无参构造参数"); } public void play(){ System.out.println("正在播放音乐...."); } }
package soundsystem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class CdPlayer { private CompactDisc cd; public CdPlayer() { super(); System.out.println("Cdplayer无参构造函数"); } @Autowired public CdPlayer(CompactDisc cd) { this.cd = cd; System.out.println("CdPlayer的有参构造函数"); } public void play(){ cd.play(); } }
package soundsystem; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; @ComponentScan public class App { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(App.class); CdPlayer player = context.getBean(CdPlayer.class); player.play(); } }
使用配置类
把主类与@ComponentScan进行解耦
@Configuration:当前的类是一个配置类 新建AppConfig(配置类)
package soundsystem; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; //配置类 @Configuration @ComponentScan public class AppConfig { }原来的主类:
package soundsystem; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class App { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); CdPlayer player = context.getBean(CdPlayer.class); player.play(); } }
使用junit单元测试
加入junit的jar包
group 'com.yuan.wiringAuto' version '1.0-SNAPSHOT' apply plugin: 'java' sourceCompatibility = 1.8 repositories { jcenter() } dependencies { // https://mvnrepository.com/artifact/org.springframework/spring-context compile group: 'org.springframework', name: 'spring-context', version: '4.3.13.RELEASE' testCompile group: 'junit', name: 'junit', version: '4.12' // https://mvnrepository.com/artifact/log4j/log4j compile group: 'log4j', name: 'log4j', version: '1.2.17' // https://mvnrepository.com/artifact/junit/junit testCompile group: 'junit', name: 'junit', version: '4.12' }单元测试的包必须跟main/java下的包一致
AppTest:
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自带的test模块
引入jar包:
// https://mvnrepository.com/artifact/org.springframework/spring-test testCompile group: 'org.springframework', name: 'spring-test', version: '4.3.13.RELEASE'
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):自动初始化spring上下文环境 @RunWith(SpringJUnit4ClassRunner.class) //自动读取配置文件 @ContextConfiguration(classes = AppConfig.class) public class AppTest { @Autowired private CdPlayer player; @Test public void testPlay(){ player.play(); } }
使用接口开发
1. @Component写在实现类上
2. 再调用时声明接口类型的成员变量
UserService:
package com.yuan.demo.service; public interface UserService { void add(); }UserServiceNormal:
package com.yuan.demo.service.impl; import com.yuan.demo.service.UserService; import org.springframework.stereotype.Component; @Component public class UserServiceNormal implements UserService { @Override public void add() { System.out.println("添加用户"); } }AppConfig:
package com.yuan.demo.service; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan public class AppConfig { }
test:
package com.yuan.demo.service; 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(); } }
自动装配的歧义性
有两个实现类的时候,autowired userservice的时候不知道注入哪一个
package com.yuan.demo.service.impl; import com.yuan.demo.service.UserService; import org.springframework.stereotype.Component; @Component public class UserServiceNormal implements UserService { @Override public void add() { System.out.println("添加用户"); } }
package com.yuan.demo.service.impl; import com.yuan.demo.service.UserService; import org.springframework.stereotype.Component; @Component public class UserServiceFestival implements UserService { @Override public void add() { System.out.println("注册用户并发送优惠券"); } }
解决办法
(1)直接声明具体的Userservice
package com.yuan.demo.service; import com.yuan.demo.service.impl.UserServiceNormal; 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 UserServiceNormal userService; @Test public void testAdd(){ userService.add(); } }(2)使用首选bean @Primary
package com.yuan.demo.service.impl; import com.yuan.demo.service.UserService; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component @Primary public class UserServiceFestival implements UserService { @Override public void add() { System.out.println("注册用户并发送优惠券"); } }
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(); } }
(3)使用限定符
类定义的时候不需要明确使用用哪个,测试的时候指定就可以了
package com.yuan.demo.service.impl; import com.yuan.demo.service.UserService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component @Qualifier("normal") public class UserServiceNormal implements UserService { @Override public void add() { System.out.println("添加用户"); } }
package com.yuan.demo.service.impl; import com.yuan.demo.service.UserService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component @Qualifier("festival") public class UserServiceFestival implements UserService { @Override public void add() { System.out.println("注册用户并发送优惠券"); } }
package com.yuan.demo.service; import com.yuan.demo.service.impl.UserServiceNormal; 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(); } }
在声明的时候指定bean的id(@Component("normal"),默认id是首字母小写的类名),在装配的时候使用@Qualifier
package com.yuan.demo.service.impl; import com.yuan.demo.service.UserService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component("normal") public class UserServiceNormal implements UserService { @Override public void add() { System.out.println("添加用户"); } }
package com.yuan.demo.service.impl; import com.yuan.demo.service.UserService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component("festival") public class UserServiceFestival implements UserService { @Override public void add() { System.out.println("注册用户并发送优惠券"); } }
package com.yuan.demo.service; import com.yuan.demo.service.impl.UserServiceNormal; 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("festival") private UserService userService; @Test public void testAdd(){ userService.add(); } }(5)java标准解决方法
在test的时候使用@Resource(name="festival"),可以替代 @Autowired + @Qualifier("festival")
package com.yuan.demo.service; import com.yuan.demo.service.impl.UserServiceNormal; 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; import javax.annotation.Resource; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = AppConfig.class) public class UserServiceTest { @Resource(name="festival") private UserService userService; @Test public void testAdd(){ userService.add(); } }
处理分层架构
浏览器——》web层(controller)——》业务层(service)——》数据访问层(dao)——》数据库
三层架构模型,逐层编写代码
通过xml启动组件扫描
在resources包下新建 applicationContext.xml, App.config配置类可以删除:
<?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.yuan.demo" /> </beans>
test:
package com.yuan.demo.controller; import com.yuan.demo.AppConfig; 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("classpath:applicationContext.xml") public class UserControllerTest { @Autowired private UserController userController; @Test public void testAdd(){ userController.add(); } }