荐 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表达式
1.简介
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>
持久层
/**
* 账户的持久层实现类
*/
@Repository(value = "accountDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private QueryRunner 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);
}
}
}
业务层
/**
* 账户的业务层实现类
*/
@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的方式自动装配。
链接: 对Spring深入的理解 | 概念的总结
链接: Spring IOC详解
链接: Spring AOP详解
链接: Spring 事务详解
如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客
本文地址:https://blog.csdn.net/weixin_45606067/article/details/107090038