Spring
一、什么是Spring?
Spring是由Rod Johnson组织开发的一个分层轻量级开源框架,以IOC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)为内核,
没学Spring的时候,是这么开发Web项目的:
• 1. 实体类—>class User{ }
• 2. daoclass–> UserDao{ … 访问db}
• 3. service—>class UserService{ UserDao userDao = new UserDao();}
• 4. actionclass UserAction{UserService userService = new UserService();}
用户访问:Tomcat->servlet->service->dao
二、Spring可以分为6 大模块:
• Spring Core Spring的核心功能: IOC容器, 解决对象创建及依赖关系
• Spring Web Spring对web模块的支持。
– 可以与struts整合,让struts的action创建交给spring
– spring mvc模式
• Spring DAO Spring 对jdbc操作的支持 【JdbcTemplate模板工具类】
• Spring ORM spring对orm的支持:
– 既可以与hibernate整合,【session】
– 也可以使用spring的对hibernate操作的封装
• Spring AOP 切面编程
• SpringEE spring 对javaEE其他模块的支持
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zbzKF6mb-1612319890080)(file:///C:/Users/十里/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]
三、Spring的核心容器:
Spring容器不单单只有一个,可以归为两种类型
• Bean 工厂,BeanFactory 【功能简单】
• 应用上下文,ApplicationContext【功能强大,一般我们使用这个】
1.BeanFactory就是一个管理Bean的工厂,它主要负责初始化各种Bean并调用他们的生命周期方法。
BeanFactory beanFactory=new XmlBeanFactory(new FileSystemResource("D:/applicationContext.xml"));
这种加载方式了解即可。
2.ApplicationContext是BeanFactory的子接口,也被称为上下文,是另一种Spring容器。
(1)通过 ClassPathXmlApplicationContext 创建
ApplicationContext ac=new ClassPathXmlApplicationContext(String ConfigLocation);
//configLocation为Spring配置文件的名称和位置。
(2) 通过 FileSystemXmlApplicationContext 创建
ApplicationContext ac=new FileSystemXmlApplicationContext(String ConfigLocation);
/*configLocation指定配置文件的位置,如果参数中写的不是绝对路径,那么方法调用的时候,会默认用绝对路径来找。
采用绝对路径的的方式会是程序的灵活性变差,所以一般不采用。
*/
四、IOC 控制反转
Spring的核心思想之一:Inversion of Control , 控制反转 IOC
那么控制反转是什么意思呢???对象的创建交给外部容器完成,这个就叫做控制反转。
• Spring使用控制反转来实现,对象不用在程序中写死
• 控制反转解决对象处理问题【把对象交给别人创建】
那么对象和对象之间的依赖关系Spring是怎么做的呢??依赖注入:dependency injection.
• Spring使用依赖注入来实现对象之间的依赖关系
• 在创建完对象之后,对象的关系处理就是依赖注入
上面已经说了,控制反转是通过外部容器完成的,而Spring又为我们提供了这么一个容器,我们一般将这个容器叫做:IOC容器.
无论是创建对象、处理对象之间的依赖关系、对象创建的时间还是对象的数量,我们都是在Spring为我们提供的IOC容器上配置 对象的信息就好了。
知乎:Spring IOC 有什么好处:https://www.zhihu.com/question/23277575/answer/24259844
ioc的思想最核心的地方在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。
也就是说,甲方要达成某种目的不需要直接依赖乙方,它只需要达到的目的告诉第三方机构就可以了,比如甲方需要一双袜子,而乙方它卖一双袜子,它要把袜子卖出去,并不需要自己去直接找到一个卖家来完成袜子的卖出。它也只需要找第三方,告诉别人我要卖一双袜子。这下好了,甲乙双方进行交易活动,都不需要自己直接去找卖家,相当于程序内部开放接口,卖家由第三方作为参数传入。甲乙互相不依赖,而且只有在进行交易活动的时候,甲才和乙产生联系。反之亦然。这样做什么好处么呢,甲乙可以在对方不真实存在的情况下独立存在,而且保证不交易时候无联系,想交易的时候可以很容易的产生联系。甲乙交易活动不需要双方见面,避免了双方的互不信任造成交易失败的问题。因为交易由第三方来负责联系,而且甲乙都认为第三方可靠。那么交易就能很可靠很灵活的产生和进行了。这就是ioc的核心思想。生活中这种例子比比皆是,支付宝在整个淘宝体系里就是庞大的ioc容器,交易双方之外的第三方,提供可靠性可依赖可灵活变更交易方的资源管理中心。另外人事代理也是,雇佣机构和个人之外的第三方。
一、在Eclipse中,创建一个名为chapter01的Web项目,将Spring的4个基础包以及commons-logging的JAR包复制到lib目录中,并发布到类路径下。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GGJ2M3q3-1612319890084)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928082944398.png)]
二、在src目录下,创建一个com.itheima.ioc包,并在包中创建接口UserDao,然后在接口中定义一个say()方法。
package com.itheima.ioc;
public interface UserDao {
public void say();
}
三、在com.itheima.ioc包下,创建UserDao接口的实现类UserDaoImpl,该类需要实现接口中的say()方法,并在方法中编写一条输出语句。
package com.itheima.ioc;
public class UserDaoImpl implements UserDao {
public void say() {
System.out.println("userDao say hello World !");
}
}
四、在src目录下,创建Spring的配置文件applicationContext.xml,并在配置文件中创建一个id为userDao的Bean。
<?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
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<bean id="userDao" class="com.itheima.ioc.UserDaoImpl" />
</beans>
五、在com.itheima.ioc包下,创建测试类TestIoC,并在类中编写main()方法。在main()方法中,需要初始化Spring容器,并加载配置文件,然后通过Spring容器获取userDao实例(即Java对象),最后调用实例中的say()方法。
package com.itheima.ioc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestIoC {
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.say();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aMdhrUio-1612319890088)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928083648186.png)]
可以看到控制台成功输出了UserDaoImpl类中的输出语句,但是在main方法中并没有通过new来创建UserDao接口的实现类对象,而实通过Spring容器来获取的实现类对象。这就是Spring IOC容器的工作机制。
五、DI依赖注入
依赖注入的实现方式:
(1)属性setter方法注入:
Spring容器使用setter方法注入被依赖的实例,通过调用无参构造方法或无参静态工厂方法实例化Bean后,调用该Bean的setter方法,即可实现基于setter方法的依赖注入。
package com.itheima.ioc;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void say() {
this.userDao.say();//调用UserDao的say()方法。
System.out.println("userService say hello World !");
}
}
在配置文件applicationContext.xml中,创建一个id为userService的Bean,该Bean用于实例化UserServiceImpl类的信息,并将 userDao的实例注入到userService中。
<bean id="userService" class="com.itheima.ioc.UserServiceImpl">
<property name="userDao" ref="userDao" />
</bean>
(2)构造方法注入:
指Spring容器使用构造方法注入被依赖的对象,通过带参数的构造方法来实现,每个参数代表一个依赖。
(3)内部bean
我们刚才是先创建userDao对象,再由userService对userDao对象进行引用…我们还有另一种思维:先创建userService,发现userService需要userDao的属性,再创建userDao…我们来看看这种思维方式是怎么配置的:
applicationContext.xml配置文件:property节点内置bean节点
<!--
1.创建userService,看到有userDao这个属性
2.而userDao这个属性又是一个对象
3.在property属性下又内置了一个bean
4.创建userDao
-->
<bean id="userService" class="UserService">
<property name="userDao">
<bean id="userDao" class="UserDao"/>
</property>
</bean>
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QLLggo5M-1612319890094)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928150143683.png)]
我们发现这种思维方式和服务器访问的执行顺序是一样的,但是如果userDao要多次被其他service使用的话,就要多次配置了…
(4)注解方式注入
(5)p命名空间方式注入属性值
p名称控件这种方式其实就是set方法的一种优化,优化了配置而已…p名称空间这个内容需要在Spring3版本以上才能使用…我们来看看:
applicationContext.xml配置文件:使用p名称空间
<bean id="userDao" class="UserDao"/>
<!--不用写property节点了,直接使用p名称空间-->
<bean id="userService" class="UserService" p:userDao-ref="userDao"/>
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4tEX363o-1612319890097)(file:///C:/Users/十里/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]
六、Bean的实例化
(1)构造器实例化:
指Spring容器通过Bean对应类中的默认无参构造方法来实例化Bean。
(2)静态工厂实例化:
此方法需要创建一个静态工厂的方法来创建Bean的实例。
1.首先创建MyBeanFactory类,并在类中创建createBean()方法来返回Bean2实例
package com.lany.factory;
public class MyBeanFactory {
public static UserDao createUserDao(){
return new UserDaoImpl();
}
}
2.创建Spring配置文件beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd ">
<!-- 将静态工厂的创建的实例交与sprig
class 静态工厂的全限定类名(包名和类名)
-->
<bean id="userDaoId" class="com.lany.static_factory.MyBeanFactory"
factory-method="createUserDao"></bean>
</beans>
3.测试使用静态工厂方式能否实例化Bean。
package com.lany.factory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestFactory {
@Test
public void run1(){
//自定义实例工厂
/*MyBeanFactory myBeanFactory=new MyBeanFactory();
UserDao userDao=myBeanFactory.createUserDao();
userDao.say();*/
ApplicationContext ac=new ClassPathXmlApplicationContext("beans5.xml");
UserDao userDao=ac.getBean("userDaoId",UserDao.class);
userDao.say();
}
}
(3)实例工厂实例化
此种方法创建Bean实例采用直接创建Bean实例的方式,在配置文件中通过factory-bean属性指向配置的实例工厂,然后通过factory-method属性确定使用工厂中的哪个方法。
1.创建实例工厂类
package com.lany.factory;
/**
* 实例工厂
* @author 十里
*
*/
public class MyBeanFactory {
public UserDao createUserDao(){
return new UserDaoImpl();
}
}
2.修改配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd ">
<!-- 创建实例工厂 -->
<bean id="myBeanFactoryId" class="com.lany.factory.MyBeanFactory"></bean>
<!-- 获得userDao -->
<bean id="userDaoId" factory-bean="myBeanFactoryId" factory-method="createUserDao"></bean>
</beans>
3.测试
package com.lany.factory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestFactory {
@Test
public void run1(){
//自定义实例工厂
/*MyBeanFactory myBeanFactory=new MyBeanFactory();
UserDao userDao=myBeanFactory.createUserDao();
userDao.say();*/
ApplicationContext ac=new ClassPathXmlApplicationContext("beans5.xml");
UserDao userDao=ac.getBean("userDaoId",UserDao.class);
userDao.say();
}
}
从控制台输出结果可以看出成功的实例化了Bean。
七、Bean的作用域
通过Spring容器创建一个Bean的实例时,不仅可以完成Bean的实例化,还可以为Bean指定作用域。
Spring 4.3中为Bean的实例定义了7种作用域,如下表所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oLAqSSBF-1612319890100)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928144152669.png)]
singleton作用域:
**singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会存在一个共享的Bean实例。**singleton作用域对于无会话状态的Bean(如Dao 组件、Service组件)来说,是最理想的选择。
<bean id="scope" class="com.itheima.scope.Scope" scope="singleton"/>
//使用bean的scope属性来指定bean的作用域。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd ">
<bean id="userdaoscope" class="com.lany.scope.UserDaoImpl" scope="singleton"></bean>
</beans>
package com.lany.scope;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test_scope {
@Test
public void run1(){
ApplicationContext ac=new ClassPathXmlApplicationContext("beans_scope.xml");
UserDao userdao=(UserDao) ac.getBean("userdaoscope");
UserDao userdao1=(UserDao) ac.getBean("userdaoscope");
System.out.println(userdao);
System.out.println(userdao1);
System.out.println(userdao==userdao1);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5umR6Z20-1612319890102)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928144801483.png)]
可以看出两次的输出结果相同,说明Spring容器只创建了一个Scope类的实例。
prototype作用域:
将xml配置文件中的bean的scope属性改为prototype
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-etICN3KO-1612319890104)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928145221816.png)]
两次的输出结果并不相同,这说明在prototype作用域下,创建了俩个不同的Scope实例。
八、Bean的生命周期
Spring容器可以管理singleton作用域的Bean的生命周期,在此作用域下Spring能够精确的知道该Bean何时被创建,何时初始化完成以及何时被销毁。
对于prototype作用域的Bean,Spring只负责创建,当容器创建了Bean实例后,Bean的实例就交给客户端代码来管理,Spring容器将不再跟踪其生命周期。每次客户端请求prototype作用域的Bean时,Spring容器都会创建一个新的实例,并且不会管那些被配置成prototype作用域的Bean的生命周期。
Spring容器中Bean的生命周期流程如下图所示;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Chg7G5DX-1612319890106)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928145930221.png)]
九、Bean的装配方式
什么时Bean的装配?
Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于注解(Annotation)的装配和自动装配(其中最常用的是基于注解的装配),本节将主要讲解这三种装配方式的使用。
1、基于xml的装配
基于xml的装配就是依赖注入中对xml进行配置的几种方式:setter方法注入,构造器注入,内部bean,p命名空间。
1.创建Java类,提供有参、无参构造以及属性setter方法;
/**
使用构造注入
提供带所有参数的有参构造方法
*/
public User(String username, Integer password, List<String> list) {
super();
this.username = username;
this.password = password;
this.list = list;
}
public User() { super();}
......
/**
使用设值注入
提供默认无参构造方法
为所有属性设置setter方法
*/
//省略属性setter方法
2.创建Spring配置文件beans5.xml,使用2种方式配置Bean;
<bean id="user1" class="com.itheima.assemble.User">
<constructor-arg index="0" value="tom" />
...
</bean>
<bean id="user2" class="com.itheima.assemble.User">
<property name=“username” value=“张三” />
...
</bean>
<!-- 使用构造注入方式装配User实例 -->
<bean id="user1" class="com.lany.iteima.User">
<constructor-arg index="0" value="tom"></constructor-arg>
<constructor-arg index="1" value="123456"></constructor-arg>
<constructor-arg index="2" >
<list>
<value>"constructorvalue1"</value>
<value>"constructorvalue2"</value>
</list>
</constructor-arg>
</bean>
<!-- 使用设值注入方式装配User实例 -->
<bean id="user2" class="com.lany.iteima.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="11"></property>
<property>
<list>
<value>"constructorvalue1"</value>
<value>"constructorvalue2"</value>
</list>
</property>
</bean>
/*<constructor-arg>元素用于定义构造方法的参数,index属性表示索引(从0开始),value用于设置注入的值
*<property>元素用于调用Bean实例中setter方法完成属性赋值,从而完成依赖注入。
*/
3.创建测试类,测试程序
public class XmlBeanAssembleTest {
public static void main(String[] args) {
String xmlPath = "com/itheima/assemble/beans5.xml";
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext(xmlPath);
System.out.println(applicationContext.getBean("user1"));
System.out.println(applicationContext.getBean("user2"));
}
}
2、基于Annotation的装配
基于XML的装配可能会导致XML配置文件过于臃肿,给后续的维护和升级带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。
Spring提供了组件扫描,来进行对指定包进行扫描,对拥有注解的类进行实例化等操作。
<!--
使用注解之前,我们要先导入4+2+aop的jar包
同时引入约束 beans+context
-->
<!--组件扫描:Spring容器会扫描这个包里所有类,从类的注解信息中获取Bean的信息-->
<context:component-scan base-package="com.pngyul.domain"></context:component-scan>
</beans> 1234567
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6VtoXAa6-1612319890109)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928160717825.png)]
Spring从2.0开始引入基于注解的配置方式,并且不断的进行完善。通过注解的方式可以直接在类上定义Bean的信息,非常方便。
@Component注解来对类进行标注,它可以被Spring容器识别,Spring容器将自动将类转换为容器管理的Bean。
//使用@Component注解定义Bean ,和<bean id="user" class="com.cad.domain.User">是等效的。
@Component("account")
public class Account {
private int id;
private String name;
private String money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMoney() {
return money;
}
public void setMoney(String money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
}
}1234567891011121314151617181920212223242526272829
除了@Component外,Spring提供了三个功能和@Component等效的注解。
它们一般用于web项目,对DAO,service,web层进行注解,所以也称为Bean的衍生注解。
- @Repository:对DAO实现类进行注解
- @Service:对service实现类进行注解
- @Controller:对web层Controller实现类进行注解
之所以提供这三个特殊的注解,是为了让注解类本身的用途清晰化,此外,Spring还赋予了一些特殊的功能。我们在项目开发中应该尽量使用这种形式
注解方式配置Bean的作用范围和生命过程方法
通过注解配置的Bean和通过< bean >配置的Bean一样,默认的作用范围都是singleton,Spring为注解配置提供了一个@Scope的注解,显式指定Bean的作用范围。
@Controller("user")
//指定作用范围为多例prototype
@Scope("prototype")
public class User {
public void say(){
System.out.println("hello.word");
}
}12345678
Spring定义的@PostConstruct和@PreDestroy两个注解相当于bean的init-method和destory-method属性的功能
@Controller("account")
@Scope("prototype")
public class Account {
public void save() {
System.out.println("hello.word");
}
@PostConstruct
public void myinit() {
System.out.println("初始化....");
}
@PreDestroy
public void mydestory() {
System.out.println("销毁中....");
}
}123456789101112131415161718
注解方式注入一般类型属性
Spring为我们提供了注解 @value,用于对一般属性注入,可以不用提供set方法
@Value("Tom")
private String nmae;
@Value("22")
private int age;
//它是通过反射的Field赋值,破坏了封装性123456
提供set方法的也可以这样注入
@Value("Tom")
Public void setName(String name){
this.name = name;
}
//通过set方法赋值,推荐使用.123456
然而在实际开发者中,尽管实际是破坏了对象的封装性,但开发者还是喜欢用第一种方式注入属性
注解方式注入引用类型属性
//会根据类型自动注入
@Autowired
private UserService userservice;123
//@Autowired可以对类成员变量的set方进行注解。
//对set方法使用注解,UserDao的实例就会被注入进来
@Autowired
public void setUserdao(UserDao userdao){
this.userdao=userdao;
}123456
问题:@Autowired默认按类型匹配的方式,在容器中查找匹配的Bean,当有且只有一个匹配的Bean时,Spring将其注入到@Autowired注解的变量中。但是如果容器中有超过一个以上的匹配Bean时,例如有两个UserService类型的Bean,这时就不知道将哪个Bean注入到变量中,就会出现异常
为了解决这个问题,Spring可以通过@Qualifier注解来注入指定Bean的名称。
public class UserAction {
@Autowired
//指定指定Bean的名称
@Qualifier("userservice")
private UserService userservice;
}123456
还有一种更为便捷的注解方式注入属性@Resource,相当于@Autowired 和@Qualifier一起使用
@Resource(name="userservice")
private UserService userservice;12
整合多个Spring配置文件
对于一个大型项目而言,可能有多个XML配置文件,在启动Spring容器时,可以通过一个String数组指定这些配置文件。Spring还允许我们通过< import >标签将多个配置文件引入到一个文件中,进行配置文件的集成,这样启动Spring容器时,就仅需指定这个合并好的配置文件即可。
- 第一种方式,使用String数组指定所有配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext(new String[]{"bean1.xml","bean2.xml"});1
- 第二种方式,使用import标签
//resource属性指定配置文件位置,支持Spring标准的资源路径
<import resource="classthpath:com/cad/domain/bean1.xml"/>
<import resource="classthpath:com/cad/domain/bean2.xml"/>123
第一种方式并不容易维护,我们在开发中推荐使用第二种方式。
spring与JUnit整合测试
以前,我们在测试的时候,都要写 ApplicationContext ac=new ClassPathXmlApplicationContext(“applicationContext.xml”),然后再获取bean对象。
现在使用JUnit,可以直接使用注解来配置,不再需要手写代码
例如下面这个例子:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
@Resource(name="accountService")
private AccountService as;
@Test
public void fun1(){
as.transfer(1, 2, 100d);
}
3、自动装配
所谓自动装配,就是将一个Bean自动的注入到到其他Bean的Property中。 Spring的元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。autowire属性有5个值,其值及说明下表所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q4UHZbor-1612319890112)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928172030649.png)]
思考:Bean的实例化和依赖注入区别
依赖注入是:一个对象要调用另一个对象时,通常是采用new的方式来创建对象,而Spring的依赖注入是由Spring容器来创建的,Spring容器将依赖对象负责把被依赖的对象赋值给调用者的成员变量,这就相当于依赖注入。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7qJ4HJJA-1612319958438)(https://raw.githubusercontent.com/lanygemini/MyImage/main/image-20200928144152669.png#pic_center)]