Day_one
总结:
将类的创建控制器交给Spring,而且,Spring除了可以通过有参构造方法,还可以通过set方法来注入依赖(记得声明成员变量)
注意:
如果没有特别强调,所有配置的数据都在applicationContext.xml中
5、快速入门—概述
执行步骤:
①导入 Spring 开发的基本包坐标
②编写 Dao 接口和实现类
③创建 Spring 核心配置文件
④在 Spring 配置文件中配置 UserDaoImpl
⑤使用 Spring 的 API 获得 Bean 实例
6、快速入门
0、配置Spring(pom.xml)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
1、appliationContext
<bean id="userDao" class="cn.itcast.dao.Impl.UserDaoImpl"></bean>
2、UserDaoImpl
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("测试一下....");
}
3、UserDaoDemo
public class UserDaoDemo {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
userDao.save();
}
7、Bean标签基本配置
谈一谈singletion和prototype:
Demo:
- singletion
输出:
- prototype:
结论:
singletion只能创建同1个对象,prototype可以创建不同的多个对象。
8、Bean标签范围配置
关于singletion:
当Spring核心配置,文件被加载时,实例化配置的Bean实例
是什么意思?
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
new ClassPathXmlApplicationContext:创建Spring容器
new ClassPathXmlApplicationContext(“applicationContext.xml”):创建Spring容器并加载配置文件。(加载配置文件就实例化了Bean的实例)
关于prototype:
当调用getBean()方法时实例化Bean
9、Bean生命周期配置
init-method:指定类中的初始化方法名称 【对象执行构造方法之后,初始化之后执行】
destroy-method:指定类中销毁方法名称【服务器ortomcat程序关闭时执行】
在实现类中指定方法名在Bean配置的属性中充当
init-method
或者destroy-method
<bean id="xxx" class="xxx" init-method="方法名">
10、Bean实例化三种方式
1) 使用无参构造方法实例化【重点学习】
它默认会根据无参构造方法来创建类对象,然而,如果bean中没有默认无参构造函数,将会创建失败【需要被实例的Bean一定要有无参构造】
配置文件:
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
2) 工厂静态方法实例化
工厂的静态方法返回Bean实例
工厂类:
public class StaticFactoryBean {
public static UserDao createUserDao(){
return new UserDaoImpl();
}
}
配置文件:
<bean id="userDao" class="com.itheima.factory.StaticFactoryBean" factory-method="createUserDao" />
3) 工厂实例方法实例化
工厂的非静态方法返回Bean实例
工厂类:
public class DynamicFactoryBean {
public UserDao createUserDao(){
return new UserDaoImpl();
}
}
配置文件:
<bean id="factoryBean" class="com.itheima.factory.DynamicFactoryBean"/>
<bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/>
------------------------------------------------------------------------
解析:
创建工厂类对象:<bean id="factoryBean" class="com.itheima.factory.DynamicFactoryBean"/>
通过工厂类对象调用createUserDao方法:<bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/>
我们来谈一谈,工厂静态方法
和工厂实例方法
的区别:
- 工厂类:
前者是静态方法,后者非静态- 配置Bean:
前者,直接通过寻找方法名可以调用(因为是静态的)
后者,需要创建工厂类对象再通过该对象找到指定方法返回我们期盼的Bean实例
11、Bean的依赖注入入门
如果像以前的逻辑去创建对象去使用对象,那么我们在使用UserService实例和UerDao实例的时候,都会在程序的代码中(Spring容器外部)逐一创建出来,然后再使用。但是,这样有什么不好的地方吗?
代码显示:
①创建 UserService,UserService 内部在调用 UserDao的save() 方法【service内部创建dao】
public class UserServiceImpl implements UserService {
@Override
public void save() {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.save();
}
}
②将 UserServiceImpl 的创建权交给 Spring【dao也给了】
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"/>
<bean id="UserD" class="com.itheima.service.impl.UserDaoImpl"/>
③从 Spring 容器中获得 UserService 进行操作
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.save();
12、Bean的依赖注入入门
然后,你会发现Service依赖dao(谁需要谁,谁就依赖谁)。而,上图这样创建对象来使用的话,会造成弊端。
什么弊端?
- 1、service与dao的耦合度强。
- 2、需要在Spring容器外部创建2个对象
什么是Spring容器内部、什么是Spring容器外部?
容器内部: Spring加载ApplicationContext.xml配置文件就会创建1个Spring容器,Bean在AplicationContest.xml配置,对象就会在容器内(将Bean创建对象的控制权Spring)
容器外部: 程序代码中。
什么是依赖?注入什么?
依赖: 我们在使用1个对象时,这个对象可能需要通过另一个对象来执行逻辑代码(比如,UserServiceImpl需要UserDaoIpml) ,这个对象可能还需要某些成员变量。
而,“另一个对象”和“某些成员变量”就是我们需要注入的东西。
怎么解决?
你service对象不是需要dao对象么?你只要给我创建对象的控制权(bean配置:2个都要),我就在Spring内部帮你把dao对象注入给你,你到时候使用的时候不需要在内部创建dao了,直接用就好了。
怎么注入依赖?
- 构造方法
- set方法
代码演示:
set方法是property标签。
①配置Spring容器调用set方法进行注入
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/> //name为UserDaoImpl属性名称
</bean>
将创建dao对象的控制权交给Spring:
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
将创建service对象的控制权交给Spring:
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
</bean>
注入依赖:
<property name="userDao" ref="userDao"/>
name="userDao":被注入依赖对象的属性名【setXXX中的XXX】
ref="userDao":注入依赖的id标识
②在UserServiceImpl中添加setUserDao方法
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
}
温馨提示:
请注意:成员变量和属性是不一样的。属性是setXXX/getXXX中的XXX,而且第一个X要小写。
13、Bean的依赖注入概念
依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。
IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。
简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取
14、Bean的依赖注入方式
p:userDao-ref="userDao":
=p:userDao-ref="对象的id标识"
补充:
UserDaoIpml的Bean也要配置。
15、Bean的依赖注入方式
(constructor(构造函数)关键字)
①创建有参构造
public class UserServiceImpl implements UserService {
private UserDao userDao;
//无参构造
public UserServiceImpl() {
}
//有参构造
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
② 配置Spring容器调用有参构造时进行注入
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
* 配置UserDao对象的Bean:
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
* 配置sevice对象的Bean:
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
* 依赖注入:
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
userDao表示构造方法的参数名:name="userDao"
userDao表示注入对象的id表示:ref="userDao"
16、Bean的依赖注入的数据类型
上面的操作,都是注入的引用Bean(关键字ref),除了对象的引用可以注入,普通数据类型,集合等都可以在容器中进行注入
注入数据的三种数据类型
UserDaoIpml
public class UserDaoImpl implements UserDao {
private String company;
private int age;
public void setCompany(String company) {
this.company = company;
}
public void setAge(int age) {
this.age = age;
}
public void save() {
System.out.println(company+"==="+age);
System.out.println("UserDao save method running....");
}
}
配置Bean:
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="company" value="传智播客"></property>
<property name="age" value="15"></property>
</bean>
*配置userDao的Bean:
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
*注入依赖:
String : <property name="company" value="传智播客"></property>
int : <property name="age" value="15"></property>
* name:注入的数据类型名称
* value:注入数量类型的内容(对象是ref)
18、Bean的依赖注入的数据类型
public class UserDaoImpl implements UserDao {
private List<String> strList;
public void setStrList(List<String> strList) {
this.strList = strList;
}
public void save() {
System.out.println(strList);
System.out.println("UserDao save method running....");
}
}
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="strList">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
</bean>
* name:被注入对象的属性名
* value:注入的属性值
public class UserDaoImpl implements UserDao {
private List<User> userList;
public void setUserList(List<User> userList) {
this.userList = userList;
}
public void save() {
System.out.println(userList);
System.out.println("UserDao save method running....");
}
}
<bean id="u1" class="com.itheima.domain.User"/> 【一个User对象Bean】
<bean id="u2" class="com.itheima.domain.User"/> 【另一个User对象Bean】
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="userList">
<list>
<ref bean="u1"/> 【注入User】
<ref bean="u2"/> 【注入User】
</list>
</property>
</bean>
public class UserDaoImpl implements UserDao {
private Map<String,User> userMap;
public void setUserMap(Map<String, User> userMap) {
this.userMap = userMap;
}
public void save() {
System.out.println(userMap);
System.out.println("UserDao save method running....");
}
}
<bean id="u1" class="com.itheima.domain.User"/>
<bean id="u2" class="com.itheima.domain.User"/>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="userMap">
<map>
<entry key="user1" value-ref="u1"/> 【key=”xxx“中xxx是自定义的id标识,标识指定key的value】
<entry key="user2" value-ref="u2"/> 【value-ref:ref注入对象引用嘛,谁的引用?就是上面Bean的引用】
</map>
</property>
</bean>
public class UserDaoImpl implements UserDao {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
public void save() {
System.out.println(properties);
System.out.println("UserDao save method running....");
}
}
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="properties">
<props>
<prop key="p1">aaa</prop> 【key是自定义的id标识】
<prop key="p2">bbb</prop>
<prop key="p3">ccc</prop>
</props>
</property>
</bean>
19、引入其他配置文件(分模块开发)
为什么要引入其他配置文件?
因为如果所有五花八门的类别的Bean什么的,都放在1个配置文件那里,那么整个配置文件不仅庞大且凌乱得难以维护。所以,我们要把不同类别的配置数据分好类提取到分模块,再把它们引入主模块中。
怎么引入?
<import resource="applicationContext-xxx.xml"/>
Spring配置总结:
20 、spring相关API—1
a)ApplicationContext的继承体系
applicationContext:接口类型,代表应用上下文,可以通过其实例获得 Spring 容器中的 Bean 对象
b)ApplicationContext的实现类
1)ClassPathXmlApplicationContext
它是从类的根路径下加载配置文件 推荐使用这种
2)FileSystemXmlApplicationContext
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
3)AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
21 、spring相关API—2
getBean源码:
2个的区别:
通过id创建:适合多个同一对象的创建(Bean),只有1个也行
通过类型的字节码文件创建:适合只有1个对象创建(Bean),如果是多个同一对象类型就会报错。