三种方式:
  1. 隐式的bean发现机制和自动装配(常用)
  2. 在java中进行显示的配置
  3. 在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();
    }
}

(4)使用限定符和类id
在声明的时候指定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();
    }
}