使用注解配置spring及junit4整合spring

使用注解配置spring

导包4(beans,context,core,expression)+2(hamcreate-core-1.3,junit-4.1)+1(spring-aop)

  1. 为主配置文件引入新的命名空间(约束,除开spring beans 还需要 spring context)
  2. 开启使用注解代替配置文件
  3. 在类中使用注解完成配置
  4. 将对象注册到容器中
  5. 修改对象的作用范围
  6. 值类型注入
  7. 引用类型注入
  8. 初始化和销毁方法

代码模块

  • User

package com.example.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

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

/**
 * @Component("user")将User bean让扫描组件可扫描到,并取名为user
 * 相当于<bean name="user" class="com/example/bean/User"></bean>
 * 注入到扫描组件扫描@Component
 * 后又引进了三个注解以作区分,其本质上没有任何区别
 * @Service service层
 * @Controller web层
 * @Repository dao层
 */
@Component("user")
/**
 * @Scope(scopeName = "prototype")作用范围,scope默认为singleton单例,这里设置的为原型,也就是多例
 */
/**
 *  @Value("杨千嬅")赋值,相当于<bean value=""></bean>
 */
//@Scope(scopeName = "prototype")
@Scope(scopeName = "singleton")
public class User {
    /**
     * 矛盾点:在日常工作中多数人都是直接在属性上赋值,而不是在set方法上赋值。其两者间效果是一致的。看公司要求或个人习惯使用。
     * @Value赋值有两种赋值,除了直接在属性上赋值也可以在,这个本质是通过反射的filed赋值
     * 其坏处是加在属性值上,破坏了面向对象中的封装思想,这里是直接操作私有化属性值。而不是通过set,get方法去访问它
     *
     * @Value("吴俊")
     * public void setName(String name) {
     *         this.name = name;
     *     }
     *     上赋值,这个本质是通过set方法赋值
     *     在set方法上赋值推荐使用
     */
    @Value("杨千嬅")
    private String name;
    /**
     * @Value("18")==@Value(Value="18")
     * 1.自定义注解只有一个属性时,且属性名为value时,赋值时value可省略。
     */

    @Value("18")
    private Integer age;

    //给Car对象赋值时,需要先将Car对象注册到扫描组件中供其扫描@Component("car")
    /**
     *
     * @Autowired自动装配,只需去car class中给其私有对象赋值即可
     * 引用类型赋值,自动装撇是根据类型查找的,当你car对象有多个时会发生什么???
     * 测试,在spring配置文件中新增一个car2去测试
     * 问题发生了,如果匹配了多个类型一致的对象,将无法选择具体注入哪一个对象
     * 解决办法使用注解@Qualifier,告诉spring自动装配那个名称的对象
     * 再查找
     *
     */
    //@Autowired

    //自动装配,找名为car2的车
    //@Qualifier("car2")

    /**
     *  @Autowired根据类型查找,当你查找的值有多个相同类型时,将无法确定查找哪个
     *  需要和@Qualifier("car2")指定名称配套使用,确定查找值
     *  更优解使用@Resource("car2")注解,手动注入,根据名称去查找,推荐
     */
    @Resource(name="car2")
    private Car car;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", car=" + car +
                '}';
    }

    /**
     * @PostConstruct直译为在构造之后
     * 在对象被创建之后调用,相当于init -method
     */
    @PostConstruct
    public void init(){
        System.out.println("这是初始化方法");
    }

    /**
     *  @PreDestroy直译为在对象销毁前
     *  在对象销毁前被调用,相当于destory -method
     *  这里需要注意的是调用销毁方法作用域需要为单例singleton,而不是原型
     *  原型每创建一个对象就会new一个新的对象出来,作用域为多例时,会执行两个初始化方法,而不会进入销毁方法
     */
    @PreDestroy
    public void destory(){
        System.out.println("这是销毁方法");
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }
}
  • Car

package com.example.bean;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("car")
public class Car {
    @Value("卡迪拉克")
    private String name;
    @Value("橙色")
    private String color;

    public Car(){

    }

    public Car(String name, String color) {
        this.name = name;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}
  • Demo

package com.example.annotation;

import com.example.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo {
    @Test
    public void fun(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) ac.getBean("user");//这个的user为你的组件名称
        User user2= (User) ac.getBean("user");
        //测试原型
        System.out.println(user==user2);
        //打印User
        System.out.println(user);
    }
    //测试初始化和销毁方法
    @Test
    public void fun1(){
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) ac.getBean("user");//这个的user为你的组件名称
        User user2= (User) ac.getBean("user");
        //单例 true
        System.out.println(user==user2);
        //打印User
        System.out.println(user);
        ac.close();
    }
}
  • appliactionContext.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 https://www.springframework.org/schema/context/spring-context.xsd">
    <!--引用注解前要先添加context.xsd头文件-->
   <!--开启注解 <context:component-scan base-package="com.example.bean"></context:component-scan>
   扫描组件:扫描基础包com.example.bean,扫描bean下所有类的注解。可以扩大扫描的范围com.example,此时范围为全项目下。
   注意:在扫描包时,会扫描包下所有的子孙包
   -->

    <context:component-scan base-package="com.example.bean"></context:component-scan>
    <bean name="car2" class="com.example.bean.Car">
        <property name="name" value="自行车"></property>
        <property name="color" value="黑色"></property>
    </bean>
</beans>

Junit4整合Spring

junit4整合spring步骤
1.先导入spring test包
2.使用@RunWith创建容器.SpringJUnit4ClassRunner.class。这种写法是为了让测试在Spring容器环境下执行。
3.使用@ContextConfiguration指定创建容器时使用的哪个配置文件
4.获取对象 private User u;

  • Demo2

package com.example.jtest;
import com.example.bean.Car;
import com.example.bean.User;
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()
 * 通过这个方法来指定一个类,然后它会调用这个类的指定方法,来创建当前的测试环境
 * @RunWith(SpringJUnit4ClassRunner)这个注解的作用就是帮我们创建容器
 * @ContextConfiguration("classpath:applicationContext.xml")指定创建容器时使用的是哪个配置文件
 * 这两个注解@RunWith必须配套@ContextConfiguration使用,@RunWith创建容器前必须要先读取到指定容器的配置文件
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo2 {
    /**
     * junit4整合spring
     * 往常是每写一个单元测试,就需要拿到其配置文件和其类对象,步骤重复,代码量冗余。类似Demo里的
     */
    /**
     * junit4整合spring步骤
     * 1.先导入spring test包
     * 2.使用@RunWith创建容器.SpringJUnit4ClassRunner.class。这种写法是为了让测试在Spring容器环境下执行。
     * 3.使用@ContextConfiguration指定创建容器时使用的哪个配置文件
     * 4.获取对象 private User u;
     *
     */

    //获取对象,将名为user的对象注入到u变量中
    @Resource(name="user")
    private User u;
    //将配置文件中的car2注入到c变量中
    @Resource(name = "car2")
    private Car c;
    //同类时一样,根据名称获取,这次获取的是Car对象中的局部变量值
    @Resource(name = "car")
    private Car c2;
    @Test
    public void run(){
        System.out.println(u);
        System.out.println(c);
        System.out.println(c2);
    }

}

posted @ 2021-09-06 23:49  LanceYa  阅读(237)  评论(0)    收藏  举报