前言

前两天和一个同学吃饭的时候同学跟我说了一件事,说他公司有个做了两年的人向他提出要涨薪资,他就顺口问了一个问题关于spring依赖注入的,那个要求涨薪的同学居然被问懵了。。。事后回家想了想这一块确实有点难度的就写篇文章把我自己知道的和网上整理的分享给大家,至少大家在被问到这一块的时候能答上来,不会因为这个被卡涨薪。话不多说,满满的干货都在下面了!

1.什么是Spring的依赖注入?

依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释。这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。

2. IOC的作用

降低程序间的耦合(依赖关系)
依赖关系的管理:
以后都交给spring来维护
在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明依赖关系的维护,就称之为依赖注入。

3.Spring依赖注入的几种方式

能注入的数据:有三类

基本类型和String。
其他bean类型(在配置文件中或者注解配置过的bean)。
复杂类型/集合类型。
注入的方式:有三种

使用构造函数提供。
使用set方法提供。
使用注解提供。

构造函数注入

顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置的方式,让 spring 框架来为我们注入。具体代码如下:

<!--构造函数注入:
使用的标签:constructor-arg
标签出现的位置:bean标签的内部
标签中的属性
type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
name:用于指定给构造函数中指定名称的参数赋值
================以上三个用于指定给构造函数中哪个参数赋值===================
value:用于提供基本类型和String类型的数据
ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象 优势:
在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
弊端:
改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="泰斯特"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean> <!-- 配置一个日期对象 -->
<bean id="now" class="java.util.Date"></bean>

  

Set方式注入

顾名思义,就是在类中提供需要注入成员的 set 方法。具体代码如下:

<!-- set方法注入 --->   更常用的方式
涉及的标签:property
出现的位置:bean标签的内部
标签的属性
name:用于指定注入时所调用的set方法名称
value:用于提供基本类型和String类型的数据
ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
优势:
创建对象时没有明确的限制,可以直接使用默认构造函数
弊端:
如果有某个成员必须有值,则获取对象是有可能set方法没有执行。
-->
<bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl2">
<property name="name" value="tom" ></property>
<property name="age" value="23"></property>
<property name="birthday" ref="now"></property>
</bean>

  

集合方式注入

顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。
我们这里介绍注入数组,List,Set,Map,Properties。

复杂类型的注入/集合类型的注入

用于给List结构集合注入的标签:
list,array,set
用于个Map结构集合注入的标签:
map,props

代码如下:

User类

public class User {
private String name;
private Integer age;
private Date birth; public void setName(String name) {
this.name = name;
} public void setAge(Integer age) {
this.age = age;
} public void setBirth(Date birth) {
this.birth = birth;
} public User(){
System.out.println("我被创建了...");
}
public void show(){
System.out.println("user中的show方法调用了。。。");
} @Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", birth=" + birth +
'}';
}
}

  

Person类

public class Person {
private String name;
private int age; public Person() {
} public Person(String name, int age) {
this.name = name;
this.age = age;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

  

CollectionDemo类

public class CollectionDemo {
private String[] arr;
private List<String> myList;
private Set<String> mySet;
private Map<String,String> myMap;
private Properties myProp; public void setArr(String[] arr) {
this.arr = arr;
} public void setMyList(List<String> myList) {
this.myList = myList;
} public void setMySet(Set<String> mySet) {
this.mySet = mySet;
} public void setMyMap(Map<String, String> myMap) {
this.myMap = myMap;
} public void setMyProp(Properties myProp) {
this.myProp = myProp;
} public String[] getArr() {
return arr;
} public List<String> getMyList() {
return myList;
} public Set<String> getMySet() {
return mySet;
} public Map<String, String> getMyMap() {
return myMap;
} public Properties getMyProp() {
return myProp;
}
}

  

配置文件:

<!-- 基于xml形式装配bean -->
<bean id="user" class="com.atguigu.java1.User"></bean> <!--使用get方法创建bean-->
<bean id="user2" class="com.atguigu.java1.User">
<property name="name" value="张"></property>
<property name="age">
<value>20</value>
</property>
<property name="birth" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean> <!--集合和数组类型的依赖注入-->
<bean id="demo" class="com.atguigu.java1.CollectionDemo">
<property name="arr">
<array>
<value>111</value>
<value>222</value>
<value>333</value>
</array>
</property>
<property name="myList">
<list>
<value>111</value>
<value>222</value>
<value>333</value>
</list>
</property>
<property name="mySet">
<set>
<value>111</value>
<value>222</value>
<value>333</value>
</set>
</property>
<property name="myMap">
<map>
<entry key="aaa" value="aaa"></entry>
<entry key="bbb" value="bbb"></entry>
<entry key="ccc" value="ccc"></entry>
</map>
</property>
<property name="myProp">
<props>
<prop key="aaa">aaa</prop>
<prop key="bbb">bbb</prop>
<prop key="ccc">ccc</prop>
</props>
</property>
</bean> <!--使用默认构造器创建bean-->
<bean id="person" class="com.atguigu.java1.Person">
<constructor-arg name="name" value="张三丰"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
</bean>

  

测试类:

/**
* 测试基于xml形式的spring ioc获取对象
*/
@Test
public void test3(){
ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
User user= (User) ioc.getBean("user");//在此处打断点验证对象是什么时候被创建的。
user.show();
} /**
* 采用默认构造器的形式创建bean对象
*/
@Test
public void test(){
ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
Person p= (Person) ioc.getBean("person");
Person p2= (Person) ioc.getBean("person");
System.out.println(p.toString());
}
/**
* 使用get方法进行依赖注入
*/
@Test
public void test4(){
ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
User user= (User) ioc.getBean("user2");//在此处打断点验证对象是什么时候被创建的。
System.out.println(user.toString());
} /**
* 集合和数组的依赖注入
*/
@Test
public void test5(){
ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
CollectionDemo demo= (CollectionDemo) ioc.getBean("demo");
System.out.println(Arrays.toString(demo.getArr()));
System.out.println(demo.getMyList());
System.out.println(demo.getMySet());
System.out.println(demo.getMyMap());
System.out.println(demo.getMyProp());
}

  

4.使用spring的ioc实现账户的CRUD

4.1 基于xml形式

1.引用外部属性文件

2.SPEL表达式

Spring Expression Language,Spring表达式语言,简称SpEL。支持运行时查询并可以操作对象图。
和JSP页面上的EL表达式、Struts2中用到的OGNL表达式一样,SpEL根据JavaBean风格的getXxx()、setXxx()方法定义的属性访问对象图,完全符合我们熟悉的操作习惯。 2.基本语法
SpEL使用#{…}作为定界符,所有在大框号中的字符都将被认为是SpEL表达式。 3.使用字面量
●整数:<property name="count" value="#{5}"/>
●小数:<property name="frequency" value="#{89.7}"/>
●科学计数法:<property name="capacity" value="#{1e4}"/>
●String类型的字面量可以使用单引号或者双引号作为字符串的定界符号
<property name=”name” value="#{'Chuck'}"/>
<property name='name' value='#{"Chuck"}'/>
●Boolean:<property name="enabled" value="#{false}"/> 4.引用其他bean
<bean id="emp04" class="com.atguigu.parent.bean.Employee">
<property name="empId" value="1003"/>
<property name="empName" value="jerry"/>
<property name="age" value="21"/>
<property name="detp" value="#{dept}"/>
</bean> 5.引用其他bean的属性值作为自己某个属性的值
<bean id="emp05" class="com.atguigu.parent.bean.Employee">
<property name="empId" value="1003"/>
<property name="empName" value="jerry"/>
<property name="age" value="21"/>
<property name="deptName" value="#{dept.deptName}"/>
</bean> 6.调用非静态方法
<!-- 创建一个对象,在SpEL表达式中调用这个对象的方法 -->
<bean id="salaryGenerator" class="com.atguigu.spel.bean.SalaryGenerator"/> <bean id="employee" class="com.atguigu.spel.bean.Employee">
<!-- 通过对象方法的返回值为属性赋值 -->
<property name="salayOfYear" value="#{salaryGenerator.getSalaryOfYear(5000)}"/>
</bean> 7.调用静态方法
<bean id="employee" class="com.atguigu.spel.bean.Employee">
<!-- 在SpEL表达式中调用类的静态方法 -->
<property name="circle" value="#{T(java.lang.Math).PI*20}"/>
</bean> 8.运算符
①算术运算符:+、-、*、/、%、^
②字符串连接:+
③比较运算符:<、>、==、<=、>=、lt、gt、eq、le、ge
④逻辑运算符:and, or, not, |
⑤三目运算符:判断条件?判断结果为true时的取值:判断结果为false时的取值
⑥正则表达式:matches

  

代码如下:

配置文件

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd
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-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> <bean id="accountDao" class="com.atguigu.dao.impl.AccountDaoImpl">
<property name="runner" ref="runner"></property>
</bean>
<bean id="accountService" class="com.atguigu.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<bean id="account" class="com.atguigu.domain.Account"></bean> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
</beans>

  

持久层

/*
账户的持久层实现类
*/
public class AccountDaoImpl implements IAccountDao { private QueryRunner runner; public void setRunner(QueryRunner runner) {
this.runner = runner;
} public List<Account> findAllAccount() {
try{
return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
}catch (Exception e) {
throw new RuntimeException(e);
}
} public Account findAccountById(Integer accountId) {
try{
return runner.query("select * from account where id = ? ",new BeanHandler<Account>(Account.class),accountId);
}catch (Exception e) {
throw new RuntimeException(e);
}
} public void saveAccount(Account account) {
try{
runner.update("insert into account(name,money)values(?,?)",account.getName(),account.getMoney());
}catch (Exception e) {
throw new RuntimeException(e);
}
} public void updateAccount(Account account) {
try{
runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
}catch (Exception e) {
throw new RuntimeException(e);
}
} public void deleteAccount(Integer accountId) {
try{
runner.update("delete from account where id=?",accountId);
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}

  

业务层

/*
账户的业务层实现类
*/
public class AccountServiceImpl implements IAccountService{ private IAccountDao accountDao; public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
} public List<Account> findAllAccount() {
return accountDao.findAllAccount();
} public Account findAccountById(Integer accountId) {
return accountDao.findAccountById(accountId);
} public void saveAccount(Account account) {
accountDao.saveAccount(account);
} public void updateAccount(Account account) {
accountDao.updateAccount(account);
} public void deleteAccount(Integer acccountId) {
accountDao.deleteAccount(acccountId);
}
}

  

测试类

public class Test1 {
ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void test1(){
IAccountService service= (IAccountService) ioc.getBean("accountService");
service.deleteAccount(2);
}
}

  

4.2 xml和注解的混搭

XML配置形式:

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope=""
init-method="" destroy-method="">
<property name="" value="" | ref=""></property>
</bean>

  

1.用于创建对象的

他们的作用就和在XML配置文件中编写一个标签实现的功能是一样的。

Component:
作用:用于把当前类对象存入spring容器中
属性:
value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。

Controller:一般用在表现层

Service:一般用在业务层

Repository:一般用在持久层

以上个注解他们的作用和属性与Component是一模一样。
他们是spring框架为我们提供明确的层使用的注解,使我们的层对象更加清晰。

2.用于注入数据的

他们的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的。

Autowired:
作用:自动照类型注入。只要容器中唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
如果ioc容器中没任何bean的类型和要注入的变量类型匹配,则报错。
如果Ioc容器中多个类型匹配时:

出现位置:
可以是变量上,也可以是方法上。

细节:
在使用注解注入时,set方法就不是必须的了。

Qualifier:
作用:在照类中注入的基础之上再照名称注入。在给类成员注入时不能单独使用。但是在给方法参数注入时可以。

属性:
value:用于指定注入bean的id。

Resource:
作用:直接照bean的id注入。它可以独立使用。

属性:
name:用于指定bean的id。
以上注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。
另外,集合类型的注入只能通过XML来实现。

Value:
作用:用于注入基本类型和String类型的数据。

属性:
value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式
SpEL的写法:${表达式}

3.用于改变作用范围的

他们的作用就和在bean标签中使用scope属性实现的功能是一样的。

Scope:
作用:用于指定bean的作用范围。

属性:
value:指定范围的取值。常用取值:singleton prototype

4.和生命周期相关(了解)

他们的作用就和在bean标签中使用init-method和destroy-methode的作用是一样的。

PreDestroy
作用:用于指定销毁方法。
PostConstruct
作用:用于指定初始化方法。

代码如下:

配置文件

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd
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-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> <!--设置自动扫描的包-->
<context:component-scan base-package="com.atguigu"></context:component-scan> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
</beans>

  

持久层

 

业务层

····
/** 账户的业务层实现类
*/
@Service("accountService")
public class AccountServiceImpl implements IAccountService{
@Autowired
private IAccountDao accountDao; public List<Account> findAllAccount() {
return accountDao.findAllAccount();
} public Account findAccountById(Integer accountId) {
return accountDao.findAccountById(accountId);
} public void saveAccount(Account account) {
accountDao.saveAccount(account);
} public void updateAccount(Account account) {
accountDao.updateAccount(account);
} public void deleteAccount(Integer acccountId) {
accountDao.deleteAccount(acccountId);
}
}
····

  

测试类

public class AccountServiceTest {
@Test
public void testFindAll() {
//1.获取容易
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.得到业务层对象
IAccountService as = ac.getBean("accountService",IAccountService.class);
//3.执行方法
List<Account> accounts = as.findAllAccount();
for(Account account : accounts){
System.out.println(account);
}
} @Test
public void testFindOne() {
//1.获取容易
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.得到业务层对象
IAccountService as = ac.getBean("accountService",IAccountService.class);
//3.执行方法
Account account = as.findAccountById(1);
System.out.println(account);
} @Test
public void testSave() {
Account account = new Account();
account.setName("test");
account.setMoney(12345f);
//1.获取容易
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.得到业务层对象
IAccountService as = ac.getBean("accountService",IAccountService.class);
//3.执行方法
as.saveAccount(account);
} @Test
public void testUpdate() {
//1.获取容易
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.得到业务层对象
IAccountService as = ac.getBean("accountService",IAccountService.class);
//3.执行方法
Account account = as.findAccountById(4);
account.setMoney(23456f);
as.updateAccount(account);
} @Test
public void testDelete() {
//1.获取容易
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.得到业务层对象
IAccountService as = ac.getBean("accountService",IAccountService.class);
//3.执行方法
as.deleteAccount(4);
}
}

  

4.3 纯注解配置

1.注解

该类是一个配置类,它的作用和bean.xml是一样的。

spring中的新注解:

Configuration:

作用:指定当前类是一个配置类。
细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。

ComponentScan:

作用:用于通过注解指定spring在创建容器时要扫描的包。

属性:
value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
我们使用此注解就等同于在xml中配置了:

<!--告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,
而是一个名称为context名称空间和约束中-->
<context:component-scan base-package="com.itheima"></context:component-scan>
Bean: 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中。 属性:
name:用于指定bean的id。当不写时,默认值是当前方法的名称。 细节:
当我们使用注解配置方法时,如果有方法参数,spring框架会去容器中查找没可用的bean对象。
查找的方式和Autowired注解的作用是一样的。 Import:
作用:用于导入其他的配置类。 属性:
value:用于指定其他配置类的字节码。
当我们使用Import的注解之后,Import注解的类就父配置类,而导入的都是子配置类 PropertySource: 作用:用于指定properties文件的位置。 属性:
value:指定文件的名称和路径。
关键字:classpath,表示类路径下。

  

2.spring整合junit4

说明:
1、应用程序的入口
main方法

2、junit单元测试中,没有main方法也能执行
junit集成了一个main方法
该方法就会判断当前测试类中哪些方法有 @Test注解
junit就让有Test注解的方法执行

3、junit不会管我们是否采用spring框架
在执行测试方法时,junit根本不知道我们是不是使用了spring框架,
所以也就不会为我们读取配置文件/配置类创建spring核心容器。

4、由以上三点可知
当测试方法执行时,没有Ioc容器,就算写了Autowired注解,也无法实现注入。

使用Junit单元测试:
Spring整合junit的配置:测试我们的配置
1、导入spring整合junit的jar(坐标)

2、使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的
@Runwith(SpringJUnit4ClassRunner.class)

3、告知spring的运行器,spring和ioc创建是基于xml还是注解的,并且说明位置
@ContextConfiguration

参数说明:

locations:指定xml文件的位置,加上classpath关键字,表示在类路径下。
classes:指定注解类所在地位置。
注意:当我们使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上。

代码如下:

配置类

/**
* @author Guohai
* @createTime 2020-07-13 17:14
*/
@Configuration
@ComponentScan("com.atguigu")
@Import(JdbcConfig.class)
@PropertySource("classpath:c3p0.properties")
public class SpringConfig { }

  

配置子类

/**
* @author Guohai
* @createTime 2020-07-13 17:16
*/
public class JdbcConfig {
@Bean(name="runner")
@Scope(value = "prototype")
public QueryRunner getRunner(@Qualifier("ds1") DataSource dataSource) {
QueryRunner runner = new QueryRunner(dataSource);
return runner;
} private static DataSource dataSource = null; @Bean(name="ds1")
public DataSource getDataSource() {
try {
Properties prop = new Properties();
InputStream is = JdbcConfig.class.getClassLoader().getResourceAsStream("jdbc.properties");
prop.load(is);
dataSource = DruidDataSourceFactory.createDataSource(prop);
return dataSource;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} @Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean(name="ds2")
public DataSource getDataSource2(){
try {
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
return dataSource;
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return null;
}
}

  

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest { @Autowired
private IAccountService as = null; @Test
public void testFindAll() {
//3.执行方法
List<Account> accounts = as.findAllAccount();
for(Account account : accounts){
System.out.println(account);
}
} @Test
public void testFindOne() {
//3.执行方法
Account account = as.findAccountById(1);
System.out.println(account);
} @Test
public void testSave() {
Account account = new Account();
account.setName("test anno");
account.setMoney(12345f);
//3.执行方法
as.saveAccount(account);
} @Test
public void testUpdate() {
//3.执行方法
Account account = as.findAccountById(4);
account.setMoney(23456f);
as.updateAccount(account);
} @Test
public void testDelete() {
//3.执行方法
as.deleteAccount(4);
}
}

  

5.Spring的自动装配

在spring中,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象,使用autowire来配置自动装载模式。

在Spring框架xml配置中共有5种自动装配:
(1)no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。
(2)byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。
(3)byType:通过参数的数据类型进行自动装配。
(4)constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
(5)autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。

最后

大家看完有什么不懂的可以在下方留言讨论,也可以关注我私信问我,我看到后都会回答的。也欢迎大家关注我的公众号:前程有光,金三银四跳槽面试季,整理了1000多道将近500多页pdf文档的Java面试题资料,文章都会在里面更新,整理的资料也会放在里面。谢谢你的观看,觉得文章对你有帮助的话记得关注我点个赞支持一下!

java后端开发三年!你还不了解Spring 依赖注入,凭什么给你涨薪的更多相关文章

  1. Java后端开发工程师是否该转大数据开发?

    撰写我对java后端开发工程师选择方向的想法,写给在java后端选择转方向的人 背景 看到一些java开发工程师,对java后端薪酬太悲观了.认为换去大数据领域就会高工资.觉得java后端没有前途.我 ...

  2. Java 后端开发常用的 10 种第三方服务

    请肆无忌惮地点赞吧,微信搜索[沉默王二]关注这个在九朝古都洛阳苟且偷生的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题. 严格意义上 ...

  3. 规范——Java后端开发规范

    Java后端开发规范 一.技术栈规约 二.命名规范 三.Java代码规范(注释规范.异常与日志.代码逻辑规范) 四.Mybatis与SQL规范 五.结果检查(单元测试及代码扫描) 六.安全规范 一.技 ...

  4. Java后端开发——美团(牛客)

    Java后端开发--美团(牛客) Java的基本数据类型,各自的字节数 ​ 老生常谈,不多说了. 类型 字节数 byte 1字节 short 2字节 int 4字节 long 8字节 float 4字 ...

  5. Java后端开发

    Java后端开发 名称 内容 基本框架 Spring.Mybatis Linux服务器   数据库优化   消息服务 rabbitMQ.activeMq rocketMq 缓存服务 memcached ...

  6. Java后端开发书架

    本人摘录于江南白衣文章,文章地址:http://calvin1978.blogcn.com/articles/javabookshelf.html 书架主要针对Java后端开发. 3.0版把一些后来买 ...

  7. Java后端开发奋斗之路

    本人方向:Java后端开发方向,本文中内容持续更新中 Java技术栈:https://www.cnblogs.com/wyb666/p/10222070.html 推荐书籍:<程序员代码面试指南 ...

  8. Java后端开发常用工具

    Java后端开发常用工具推荐: 俗话说,工欲善其事,必先利其器.不过初学时候不大建议过度依赖IDE等过多工具,这会让自己的编程基础功变得很差,比如各种语法的不熟悉,各种关键字比如synchronize ...

  9. 2022美团Java后端开发春招实习面经

    2022美团Java后端开发春招实习面经 一面 1.讲一下计算机网络的五层架构,每层分别有什么协议 ​ 五层架构:应用层.运输层.网络层.数据链路层.物理层 ​ 2.什么是 Http 协议,各种 Ht ...

随机推荐

  1. 攻防世界-web2

    打开题目直接一梭子代码,给我们了个加密的密文,然我们解出flag 审计一波 先时将flag字符串逆序,然后每一个ascii码数值+1,然后base64加密,然后逆序,然后再rot13加密 得到加密的密 ...

  2. 读高性能Mysql摘要

    类型相关 INT(1)和INT(20)对于存储和计算来说,意义是相同的,他不会限制值的合法范围,只是一些交互工具会用来显示字符的个数 默认是有符号的,可以指定为无符号,增加数据存储范围,如0-255, ...

  3. mysql在DOS环境下操作的命令

    管理员运行cmd,执行启动mysql命令:net start MySQL版本号 登录数据库:mysql -u root -p 输入密码 创建数据库:drop database if exists 数据 ...

  4. 专题五:redis的数据类型之set

    一.基本简介 现在出现了新的查询需求:存储大量数据的同时,还需要在查询方面提供更高的效率.虽然list满足存储大量的数据,也可以通过索引来进行访问,但是list底层是双向链表的结构,在查询上的效率并没 ...

  5. 1,web项目工作流程

    1.1 了解web程序工作流程 .1.2django生命周期

  6. PHP获取文件拓展名的方法

    1.用strrchar()函数,查找字符串在另一字符串中最后出现的位置,并返回该位置到字符串最后的所有字符(返回结果包括点).即返回拓展名前  点  到结尾的字符,即为扩展名.注意与strchar() ...

  7. Spark: JAVA_HOME is not set

    在Spark项目,sbin目录下的spark-config.sh文件下,最后添加JAVA_HOME的索引. 即可.

  8. vue3.0-如何切换路由-路由模式ts

    如何更换路由模式 vue3版本如何切换路由模式?(注:更改后要重启下项目才能看到效果.) 博主,我搜了大半天的,你是怎么找到的? 如下图可看到

  9. 【Luogu】P1072 Hankson 的趣味题 题解

    原题链接 嗯...通过标签我们易得知,这是一道数学题(废话) 其中,题目给了这两个条件: \(gcd(x,a_0)=a_1,lcm(x,b_0)=b_1\) 所以,根据 \(gcd\) 与 \(lcm ...

  10. 写时复制集合 —— CopyOnWriteArrayList

    前言 JUC 下面还有一个系列的类,都是 CopyOnWriteXXX ,意思是写时复制,这个究竟是怎么回事?那就以 CopyOnWriteArrayList 为切入点,一起了解写时复制是怎么回事? ...