Spring Ioc

Ioc控制反转
Ioc控制反转,全称Inverse of Control,是一种设计理念
由代理人来创建与管理对象,消费者通过代理人来获取对象
Ioc的目的是降低对象之间直接耦合
加入loC容器将对象统一管理,让对象关联变为弱耦合

DI 依赖注入
loC是设计理念,是现代程序设计遵循的标准,是宏观目标
DI(Dependency Injection)是具体技术实现,是微观实现
DI在Java中利用反射技术实现对象注入(Injection)

Spring的含义
Spring可从狭义与广义两个角度看待
狭义的Spring是指Spring框架(Spring Fremework)
广义的Spring是指Spring生态体系

狭义的Spring框架
Spring框架是企业开发复杂性的一站式解决方案
Spring框架的核心是IOC容器与AOP面向切面编程
Spring loC负责创建与管理系统对象,并在此基础上扩展功能

广义的Spring生态体系
在这里插入图片描述
Spring文档

在这里插入图片描述
理解这个图就理解IOC
在这里插入图片描述Spring IOC 容器职责
对象的控制权交由第三方统一管理(loC控制反转)
利用Java反射技术实现运行时对象创建与关联(DI依赖注入)
基于配置提高应用程序的可维护性与扩展性

Spring IOC 初体验

需要在pop.xml文件中添加

	<repositories>
        <repository>
            <id>aliyun</id>
            <name>aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
    </repositories>

  <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
    </dependencies>

创建两个实体类
Apple实体类

public class Apple {
    private String title;
    private String color;
    private String origin;
    public Apple() {}
    public Apple(String title, String color, String origin) {
        this.title = title;
        this.color = color;
        this.origin = origin;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public String getOrigin() {
        return origin;
    }
    public void setOrigin(String origin) {
        this.origin = origin;
    }
}
public class Child {
    private String name;
    private Apple apple;
    public Child() {}
    public Child(String name, Apple apple) {
        this.name = name;
        this.apple = apple;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Apple getApple() {
        return apple;
    }
    public void setApple(Apple apple) {
        this.apple = apple;
    }
    public void eat(){
        System.out.println(name+"吃到了"+apple.getOrigin()+"种植的"+apple.getTitle());
    }
}

之前用的方法

public class Application {
    public static void main(String[] args) {
        Apple apple1 = new Apple("红富士", "红色", "欧洲");
        Apple apple2 = new Apple("青苹果", "绿色", "中亚");
        Apple apple3 = new Apple("金帅", "黄色", "中国");
        Child lily = new Child("莉莉", apple1);
        Child andy = new Child("安迪", apple2);
        Child luna = new Child("露娜", apple3);
        lily.eat();
        andy.eat();
        luna.eat();
    }
}

这样写,如果想修改的话只能修改源码,不便于维护。

使用IOC方式
在resources文件夹下创建Spring IOC 核心配置文件 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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--在ioc容器启动时,自动由Spring实例化Apple对象,取名sweetApple放入到容器中-->
    <!-- id全局唯一	class代表要实例化哪个类 -->
    <bean id="sweetApple" class="com.imooc.spring.ioc.entity.Apple">
        <property name="title" value="红富士"/>
        <property name="origin" value="欧洲"/>
        <property name="color" value="红色"/>
    </bean>
    <!-- IOC容器自动利用反射机制运行时调用setXXX方法为属性赋值 -->
    <bean id="sourApple" class="com.imooc.spring.ioc.entity.Apple">
        <property name="title" value="青苹果"/>
        <property name="origin" value="中亚"/>
        <property name="color" value="绿色"/>
    </bean>

    <bean id="softApple" class="com.imooc.spring.ioc.entity.Apple">
        <property name="title" value="金帅"/>
        <property name="origin" value="中国"/>
        <property name="color" value="黄色"/>
    </bean>

    <bean id="rdApple" class="com.imooc.spring.ioc.entity.Apple">
        <property name="title" value="蛇果"/>
        <property name="origin" value="美国"/>
        <property name="color" value="黄色"/>
    </bean>

    <bean id="lily" class="com.imooc.spring.ioc.entity.Child">
        <property name="name" value="莉莉"/>
        <property name="apple" ref="sweetApple"/>
    </bean>

    <bean id="andy" class="com.imooc.spring.ioc.entity.Child">
        <property name="name" value="安迪"/>
        <property name="apple" ref="rdApple"/>
    </bean>

    <bean id="luna" class="com.imooc.spring.ioc.entity.Child">
        <property name="name" value="露娜"/>
        <property name="apple" ref="softApple"/>
    </bean>
</beans>
public class SpringApplication {
    public static void main(String[] args) {
        // 创建Spring IOC容器,并根据配置文件在容器中实例化对象
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "classpath:applicationContext.xml");
        // 第一个参数是在配置文件中的ID,第二个参数是哪个实体类
        // 从IOC文件中获取bean
        Apple sweetApple = context.getBean("sweetApple", Apple.class);
        System.out.println(sweetApple.getTitle());
        // 从IOC容器中提取beanId=lily的对象
        Child lily = context.getBean("lily", Child.class);
        lily.eat();
        Child andy = context.getBean("andy", Child.class);
        andy.eat();
        Child luna = context.getBean("luna", Child.class);
        luna.eat();
    }
}

如果想修改数据,只需要在applicationContext文件中修改即可。不用修改代码。

三种xml实例化Bean的配置方式

  1. 基于构造方法实例化对象(大多数用这种)
  2. 基于静态工厂类实例化方法
  3. 基于工厂实例方法实例化对象

按名称赋值

<!-- bean标签默认通过默认构造方法创建对象 -->
<!-- bean ID唯一 -->

1.基于构造方法实例化对象
在这里插入图片描述
按位置赋值(不推荐使用)
在这里插入图片描述
2.基于静态工厂类实例化方法

// 静态工厂通过静态方法创建对象,隐藏创建对象细节
// 可以额外增加一些功能
public class AppleStaticFactory {
    public static Apple createSweetApple() {
        Apple apple = new Apple();
        apple.setTitle("红富士");
        apple.setColor("红色");
        apple.setOrigin("欧洲");
        return apple;
    }
}
<!--利用静态工厂获取对象-->
    <bean id="apple3" class="com.imooc.spring.ioc.Factory.AppleStaticFactory"
          factory-method="createSweetApple"/>

3.基于工厂实例方法实例化对象

//工厂实力方法创建对象是指IOC容器对工厂类进行实例化并调用对应的实力方法创建对象的过程
class AppleFactoryInstance {
    public Apple createSweetApple(){
        Apple apple = new Apple();
        apple.setTitle("红富士");
        apple.setColor("红色");
        apple.setOrigin("欧洲");
        return apple;
    }
}
<!--利用工厂实例方法获取对象-->
    <bean id="factoryInstance" class="com.imooc.spring.ioc.Factory.AppleFactoryInstance"/>
    <bean id="apple4" factory-bean="factoryInstance" factory-method="createSweetApple"/>

id与name属性相同点
bean id与name都是设置对象在loC容器中唯一标识
两者在同一个配置文件中都不允许出现重复
两者允许在多个配置文件中出现重复,新对象覆盖旧对象

id与name属性区别
id要求更为严格,一次只能定义一个对象标识(推荐)
name更为宽松,—次允许定义多个对象标识
tips: id与name的命名要求有意义,按驼峰命名书写

如果没有id也没有name,需要使用类全称作为类标识

路径匹配表达式
加载单个文件就用上边的方法,加载多个配置文件就用个数组保存起来。
在这里插入图片描述
对象依赖注入
依赖注入是指运行时将容器内对象利用反射赋给其他对象的操作
基于setter方法注入对象(常用)
基于构造方法注入对象
在这里插入图片描述

在这里插入图片描述
构造方法创建对象

	<bean id="sourApple" class="com.imooc.spring.ioc.entity.Apple">
        <property name="title" value="青苹果"/>
        <property name="color" value="绿色"/>
        <property name="origin" value="中亚"/>
        <property name="price" value="9.78"/>
    </bean>
    <bean id="andy" class="com.imooc.spring.ioc.entity.Child">
        <constructor-arg name="name" value="安迪"/>
        <constructor-arg name="apple" ref="sourApple"/>
    </bean>

注入集合对象
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
小案例

public class Company {
    private Set<String> rooms;
    private Map<String, Computer> computers;
    private Properties info;
    public Set<String> getRooms() {
        return rooms;
    }
    public void setRooms(Set<String> rooms) {
        this.rooms = rooms;
    }
    public Map<String, Computer> getComputers() {
        return computers;
    }
    public void setComputers(Map<String, Computer> computers) {
        this.computers = computers;
    }
    public Properties getInfo() {
        return info;
    }
    public void setInfo(Properties info) {
        this.info = info;
    }
    @Override
    public String toString() {
        return "Company{" +
                "rooms=" + rooms +
                ", computers=" + computers +
                ", info=" + info +
                '}';
    }
}

public class Computer {
    private String brand;
    private String type;
    private String sn;
    private Float price;
    public Computer() {
    }
    public Computer(String brand, String type, String sn, Float price) {
        this.brand = brand;
        this.type = type;
        this.sn = sn;
        this.price = price;
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getSn() {
        return sn;
    }
    public void setSn(String sn) {
        this.sn = sn;
    }
    public Float getPrice() {
        return price;
    }
    public void setPrice(Float price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Computer{" +
                "brand='" + brand + '\'' +
                ", type='" + type + '\'' +
                ", sn='" + sn + '\'' +
                ", price=" + price +
                '}';
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="c1" class="com.imooc.spring.ioc.entity.Computer">
        <constructor-arg name="brand" value="联想"/>
        <constructor-arg name="type" value="台式机"/>
        <constructor-arg name="sn" value="8389283012"/>
        <constructor-arg name="price" value="3085"/>
    </bean>

    <bean class="com.imooc.spring.ioc.entity.Computer">
        <constructor-arg name="brand" value="微星"/>
        <constructor-arg name="type" value="台式机"/>
        <constructor-arg name="sn" value="8389283013"/>
        <constructor-arg name="price" value="6085"/>
    </bean>
    <bean class="com.imooc.spring.ioc.entity.Computer">
        <constructor-arg name="brand" value="华硕"/>
        <constructor-arg name="type" value="笔记本"/>
        <constructor-arg name="sn" value="8389283014"/>
        <constructor-arg name="price" value="7085"/>
    </bean>

    <bean id="company" class="com.imooc.spring.ioc.entity.Company">
        <property name="rooms">
            <set>
                <value>2001-总裁判</value>
                <value>2003-总经理办公室</value>
                <value>2010-研发部会议室</value>
                <value>2010-研发部会议室</value>
            </set>
        </property>
        <property name="computers">
            <map>
                <entry key="dev-88172" value-ref="c1"/>
                <entry key="dev-88173">
                    <bean class="com.imooc.spring.ioc.entity.Computer">
                        <constructor-arg name="brand" value="联想"/>
                        <constructor-arg name="type" value="台式机"/>
                        <constructor-arg name="sn" value="8389283012"/>
                        <constructor-arg name="price" value="5085"/>
                    </bean>
                </entry>
            </map>
        </property>
        <property name="info">
            <props>
                <prop key="phone">010-12345678</prop>
                <prop key="address">北京市朝阳区xx路xx大厦</prop>
                <prop key="website">www.xxx.com</prop>
            </props>
        </property>
    </bean>
</beans>

set在java中会转换成LinkHashSet
Map会在Java中转换为LinkHashMap
有序

public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "classpath:applicationContext.xml");
        Company company = context.getBean("company", Company.class);
        System.out.println(company);
        String website = company.getInfo().getProperty("website");
        System.out.println(website);
        System.out.println("============================");
        //获取容器内所有beanId数据
        String[] beanNames = context.getBeanDefinitionNames();
        for (String beanName :beanNames) {
            System.out.println(beanName);
            System.out.println("类型:"+context.getBean(beanName).getClass().getName());
            System.out.println("内容:"+context.getBean(beanName));
        }
        // 不添加编号默认是第一个
        Computer computer = context.getBean("com.imooc.spring.ioc.entity.Computer", Computer.class);
        System.out.println(computer.getBrand());
        // 添加编号获取到具体的
        computer = context.getBean("com.imooc.spring.ioc.entity.Computer#1", Computer.class);
        System.out.println(computer.getBrand());
    }
}

匿名bean会以类全称#i的显示出现
匿名bean不推荐使用

bean scope属性
bean scope属性用于决定对象何时被创建与作用范围
bean scope配置将影响容器内对象的数量
bean scope默认值singleton(单例),指全局共享同一个对象实例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
某一个属性运行过程中恒定不变可以进行单例设置
如果在不断地变化可以使用多例设置

对象生命周期

 <bean id="order1" class="com.imooc.spring.ioc.entity.Order" init-method="init" destroy-method="destroy">
        <property name="price" value="19.8"/>
        <property name="quantity" value="1000"/>
    </bean>
 Order order1 = context.getBean("order1", Order.class);
 order1.pay();
 // 销毁容器
 context.registerShutdownHook();

设置init-method之后会先创建对象,然后设置初始值。然后调用init-method指定的方法。
销毁的时候会调用destroy-method设置的方法。

自己开发一个简单的IOC容器

创建一个实例

public class Apple  {
    public String title;
    private String color;
    private String origin;
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public String getOrigin() {
        return origin;
    }
    public void setOrigin(String origin) {
        this.origin = origin;
    }
}

创建配置文件applicationContext.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans>
    <bean id="sweetApple" class="com.imooc.spring.ioc.entity.Apple">
        <property name="title" value="红富士"/>
        <property name="color" value="红色"/>
        <property name="origin" value="欧洲"/>
    </bean>
</beans>

创建一个接口

public interface ApplicationContext {
    public Object getBean(String beanId);
}

添加xml文件解析组件

<dependencies>
        <dependency>
            <!--Dom4j是Java的xml解析组件-->
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!--jaxen是xpath表达式解释器-->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.6</version>
        </dependency>
    </dependencies>
public class ClassPathXmlApplicationContext implements ApplicationContext {
	// ioc容器最基础的实现就是map
    private Map<String, Object> iocContainer = new HashMap();

    public ClassPathXmlApplicationContext() {
        try {
        	// 获取配置文件的物理地址
            String filePath = this.getClass().getResource("/applicationContext.xml").getPath();
            // 防止路径出问题 进行解码
            filePath = URLDecoder.decode(filePath, "utf-8");
            // 加载解析filePath对应的xml文件
            SAXReader reader = new SAXReader();
            // 读取指定文件 所有xml数据都包含在Document中
            Document document = reader.read(new File(filePath));
            // 先获取根节点,然后再获取指定节点的集合 集合中每一个对象都是Node节点
            List<Node> beans = document.getRootElement().selectNodes("bean");
            for (Node bean : beans) {
                Element ele = (Element) bean;
                // 获取id
                String id = ele.attributeValue("id");
                // 获取class
                String className = ele.attributeValue("class");
                
                // 加载指定的类,获取类对象 
                Class<?> c = Class.forName(className);
                // 通过默认构造方法初始化对象 利用反射初始化
                Object obj = c.newInstance();
                List<Node> properties = ele.selectNodes("property");
               	// 得到每一个属性
                for (Node p : properties) {
                    Element property = (Element) p;
                    String propName = property.attributeValue("name");
                    String propValue = property.attributeValue("value");

                    //利用反射机制注入数据
                    // 组织set方法 
                    String setMethodName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
                    System.out.println("准备执行" + setMethodName + "方法注入数据");
                    // 通过反射获取set方法
                    Method setMethod = c.getMethod(setMethodName, String.class);
                    setMethod.invoke(obj, propValue);//通过setter方法注入数据
                }
                iocContainer.put(id, obj);
            }
            System.out.println(iocContainer);
            System.out.println("Ioc容器初始化完毕");
        } catch (Exception e) {
        }
    }
    @Override
    public Object getBean(String beanId) {
        return iocContainer.get(beanId);
    }
}
public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext();
        Apple sweetApple = (Apple) context.getBean("sweetApple");
        System.out.println(sweetApple);
    }
}

基于注解与Java Config配置loC容器
基于注解配置IOC容器
优势:
摆脱繁琐的XML形式的bean与依赖注入配置
基于"声明式"的原则,更适合轻量级的现代企业应用
让代码可读性变得更好,研发人员拥有更好的开发体验

三类注解
组件类型注解-声明当前类的功能与职责
自动装配注解-根据属性特征自动注入对象
元数据注解-更细化的辅助loC容器管理对象的注解

在这里插入图片描述
首先需要干这件事
初始化ioc的时候 base-package会扫描这个包下所有的类
在这里插入图片描述

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

<!--通知Spring Ioc容器初始化加载配置文件-->
    <context:property-placeholder location="classpath:config.properties"/>
    <!--在IoC容器初始化时自动扫描四种组件类型注解并完成实例化
        @Repository
        @Service
        @controller
        @Component
        -->
    <!-- 基准包 saom -->
    <context:component-scan base-package="com.imooc"/>
</beans>
// 组件类型注解默认BeanID默认为类名首字母小写(userDao)
@Repository
public class UserDao implements IUserDao {
    public UserDao() {
        System.out.println("正在创建UserDao:" + this);
    }
}

在这里插入图片描述

@Service
@Scope("prototype")
public class UserService {
    @Value("${metaData}")
    private String metaData;
    @Value("${connection.password}")
    private String pwd;
    @PostConstruct //xml中bean init-method完全相同
    public void init() {
        System.out.println("初始化UserService对象,metaData:" + metaData + "---" + pwd);
    }
    // 按类型注解
    // @Autowired
    // Spring IoC容器会自动通过反射技术将属性private修饰符自动改为public,
    // 直接进行赋值/不再执行set方法
    @Autowired
    private IUserDao udao;
    public UserService() {
        System.out.println("正在创建UserService:" + this);
    }
    public UserService(UserDao udao) {
        this.udao = udao;
    }
    public IUserDao getUdao() {
        return udao;
    }
    @Autowired
    //如果装配注解放在set方法上,则自动按类型/名称对set方法参数进行注入
    public void setUdao(UserDao udao) {
        System.out.println("setUdao:" + udao);
        this.udao = udao;
    }
}
@Repository
// 如果在Ioc 容器中出现了多个相同类型的对象的话那么默认采用@Primary所描述的对象注入
@Primary
public class UserOracleDao implements  IUserDao{
    public UserOracleDao() {
        System.out.println("正在创建UserOracleDao:" + this);
    }
}
// 组件类型注解默认BeanID默认为类名首字母小写(userDao)
@Repository
public class UserDao implements IUserDao {
    public UserDao() {
        System.out.println("正在创建UserDao:" + this);
    }
}

在项目中通常使用按名称注入

@Service
public class DepartmentService {
    /**
     * 1. @Resource设置name属性,则按name在IoC容器中将bean注入
     * 2. @Resource未设置name属性
     * 2.1 以属性名作为bean name在IoC容器中匹配bean ,如有匹配则注入
     * 2.2 按属性名未匹配,则按类型进行匹配,同CAutowired,需加入@Primary解决类型冲突
     * 使用建议:在使用@Resource对象时推荐设置name或保证属性名与bean名称一致
     */

//    @Resource(name="userOracleDao")
//    private IUserDao udao;
    @Resource
    private IUserDao UserOracleDao;

    public void joinDepartment(){
        System.out.println(UserOracleDao);
    }
}

其他元数据注解
在这里插入图片描述

@Service
@Scope("prototype")
public class UserService {
    @Value("${metaData}")// 读取config.properties的metaData属性值
    private String metaData;

    @Value("${connection.password}")
    private String pwd;

    @PostConstruct //xml中bean init-method完全相同
    public void init() {
        System.out.println("初始化UserService对象,metaData:" + metaData + "---" + pwd);
    }

    // 按类型注解
    // @Autowired
    // Spring IoC容器会自动通过反射技术将属性private修饰符自动改为public,
    // 直接进行赋值/不再执行set方法
    @Autowired
    private IUserDao udao;

    public UserService() {
        System.out.println("正在创建UserService:" + this);
    }

    public UserService(UserDao udao) {
        this.udao = udao;
    }

    public IUserDao getUdao() {
        return udao;
    }

    @Autowired
    //如果装配注解放在set方法上,则自动按类型/名称对set方法参数进行注入
    public void setUdao(UserDao udao) {
        System.out.println("setUdao:" + udao);
        this.udao = udao;
    }
}

metaData = testData
connection.password = 123

基于Java Config配置IOC容器
优势:
完全摆脱XML的束缚,使用独立Java类管理对象与依赖
注解配置相对分散,利用Java Config可对配置集中管理
可以在编译时进行依赖检查,不容易出错

在这里插入图片描述

@Configuration // 当前是一个配置类,用于替代applicationContext.xml
@ComponentScan(basePackages = "com.imooc")// 组件扫描
public class Config {

    @Bean // java config利用方法创建对象。将方法对象返回容器,beanId=方法名
    public UserDao userDao() {
        UserDao userDao = new UserDao();
        System.out.println("已创建:" + userDao);
        return userDao;
    }
    @Bean
    // 先按照名字进行注入,name不存在则按照类型注入
    public UserService userService(UserDao userDao, EmployeeDao employeeDao) {
        UserService userService = new UserService();
        System.out.println("已创建:" + userService);
        userService.setUserDao(userDao);
        System.out.println("调用setUserDao:" + userDao);
        userService.setEmployeeDao(employeeDao);
        return userService;
    }
    @Bean
    public UserController userController(UserService userService) {
        UserController userController = new UserController();
        System.out.println("已创建:" + userController);
        userController.setUserService(userService);
        System.out.println("调用setUserDao:" + userService);
        return userController;
    }
}

public class SpringApplication {
    public static void main(String[] args) {
        // 基于 java config 配置IOC容器的初始化
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        System.out.println("================================");
        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name + "========" + context.getBean(name));
        }
    }
}
public class UserService {
    private UserDao userDao;

    private EmployeeDao employeeDao;

    public EmployeeDao getEmployeeDao() {
        return employeeDao;
    }

    public void setEmployeeDao(EmployeeDao employeeDao) {
        this.employeeDao = employeeDao;
    }

    public UserDao getUserDao() {
        return userDao;
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

Spring Test 测试模块
Spring Test是Spring中用于测试的模块
Spring Test对JUnit单元测试框架有良好的整合
通过Spring Test可在JUnit在单元测试时自动初始化loC容器

Spring与Junit4整合过程
Maven工程依赖spring-test
利用@RunWith与@ContextConfiguration描述测试用例类
测试用例类从容器获取对象完成测试用例的执行

pop文件中添加依赖

  <repositories>
        <repository>
            <id>aliyun</id>
            <name>aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
public class UserDao {
    public void insert(){
        System.out.println("新增用户属性");
    }
}

public class UserService {
    private UserDao userDao;

    public void createUser() {
        System.out.println("调用创建用户业务代码");
        userDao.insert();
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userDao" class="com.imooc.spring.ioc.dao.UserDao"/>

    <bean id="userService" class="com.imooc.spring.ioc.service.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>
</beans>
// 将Junit4的执行权交由Spring Test,在测试用例执行前自动初始化IoC容器
@RunWith(SpringJUnit4ClassRunner.class)
// 通知IOC加载哪个配置文件
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringTestor {
    @Resource //注入需要的属性
    private UserService userService;
    @Test
    public void testUserService(){
        userService.createUser();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值