文章目录
三.IOC基本操作(Bean管理)
3.1 Bean管理的两个操作:
1.Spring创建对象(下面是基于xml配置文件实现的)
2.Spring注入属性
3.2 Bean管理操作的两种方式:
3.2.1 基于xml配置文件实现
1.创建对象
在配置文件中用bean标签,标签中添加对应属性,就可以完成创建
bean标签中的常用属性
id:表示唯一标识
class:包类路径
创建对象时,默认使用无参构造方法进行对象的创建,如果定义了有参构造器,那么就会报错
2.注入属性
需要在Book类中为属性创建set方法
DI:依赖注入,
要注意在注入属性之前要先创建对象
Book类:
/**
* 输出书名和作者
*/
public class Book {
private String bookName;
private String bookAuthor;
public void setBookName(String bookName) {
this.bookName = bookName;
}
public void setBookAuthor(String bookAuthor) {
this.bookAuthor = bookAuthor;
}
public void testDemo(){
System.out.println(bookName);
System.out.println(bookAuthor);
}
xml文件:
<!-- book类中的属性注入-->
<bean id="book" class="com.ccw.spring5.day02.Book">
<!-- 使用property标签完成属性注入 -->
<!-- name:属性名 -->
<!-- value:属性注入的值 -->
<property name="bookName" value="英雄联盟"></property>
<property name="bookAuthor" value="拳头公司"></property>
</bean>
测试类:
@Test
public void testBook(){
//1.加载spring的配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
//2.获取配置创建的对象
Book book = context.getBean("book",Book.class);
book.testDemo();
}
当类中使用了有参构造器如何注入:
<!-- book类中的属性注入-->
<bean id="book" class="com.ccw.spring5.day02.Book">
<!-- 在使用有参构造器的时候要使用constructor-arg标签来注入-->
<constructor-arg name="bookName" value="英雄联盟"></constructor-arg>
<constructor-arg name="bookAuthor" value="拳头公司"></constructor-arg>
</bean>
/**
* 输出书名和作者
*/
public class Book {
private String bookName;
private String bookAuthor;
public Book(String bookName, String bookAuthor) {
this.bookName = bookName;
this.bookAuthor = bookAuthor;
}
public void testDemo(){
System.out.println(bookName);
System.out.println(bookAuthor);
}
}
3.xml注入其他类型属性
null值:
<property name="address"> <null/> </property>
<constructor-arg name="address"><null/></constructor-arg>
特殊符号:
例如《南京》:把带符号的内容写到CDATA中,
直接输入CD就有了
<property name="address"> <value><![CDATA[《南京》]]></value> </property>y>
4.外部注入bean
public class UserService {
//创建UserDao类型属性,生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add......");
userDao.update();
}
}
dao接口
public interface UserDao {
public void update();
}
dao接口实现类
public class UserDaoImpl implements UserDao {
@Override
public void update() {
System.out.println("dao update......");
}
}
xml文件
<bean id="UserServic" class="com.ccw.spring5.day03.service.UserService">
<!-- ref:创建userDao对象bean标签id值 -->
<property name="userDao" ref="UserDao"></property>
</bean>
<bean id="UserDao" class="com.ccw.spring5.day03.dao.UserDaoImpl"></bean>
</beans>
测试方法:
public class TestBean {
@Test
public void testBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
UserService userService = context.getBean("userService",UserService.class);
userService.add();
}
}
5.内部注入bean
实体类:
//部门类
public class Department {
private String name;
public void setName(String name) {
this.name = name;
}
}
@Override
public String toString() {
return "Department{" +
"name='" + name + '\'' +
'}';
}
//员工类
public class Employee {
private String name;
private String gender;//性别
private Department dept;//员工部门
public void setDept(Department dept) {
this.dept = dept;
}
public void setName(String name) {
this.name = name;
}
public void setGender(String gender) {
this.gender = gender;
}
}
xml文件:
<bean name="Employee" class="com.ccw.spring5.day04.Employee">
<property name="name" value="ccw"></property>
<property name="gender" value="男"></property>
<property name="dept">
<bean name="Department" class="com.ccw.spring5.day04.Department">
<property name="name" value="安保部"></property>
</bean>
</property>
</bean>
6.级联赋值
xml文件:
(方式1):
<bean name="employee" class="com.ccw.spring5.day04.Employee">
<property name="name" value="ccw"></property>
<property name="gender" value="男"></property>
<property name="dept" ref="Department"></property>
</bean>
<bean name="Department" class="com.ccw.spring5.day04.Department">
<property name="name" value="安保部"></property>
</bean>
(方式二):
此方式需要在实体类中添加get方法
<bean name="employee" class="com.ccw.spring5.day04.Employee">
<property name="name" value="ccw"></property>
<property name="gender" value="男"></property>
<property name="dept" ref="Department"></property>
<property name="dept.name" value="财务部"></property>
</bean>
<bean name="Department" class="com.ccw.spring5.day04.Department">
</bean>
7.注入集合类型属性
(1)注入数组类型
(2)注入List集合类型属性
(3)注入Map集合类型属性
<bean name="student" class="com.ccw.spring5.day05.Student">
<!-- 数组类型属性,property中可以用array,也可以用list -->
<property name="courses">
<array>
<value>语文</value>
<value>java</value>
</array>
</property>
<!-- list类型属性 -->
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
</list>
</property>
<!-- Map类型属性 entry标签来表示key和value-->
<property name="map">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PYTHON" value="python"></entry>
</map>
</property>
<!-- set类型属性-->
<property name="set">
<set>
<value>100</value>
<value>50</value>
</set>
</property>
</bean>
Student类:
public class Student {
//1.数组类型属性
private String[] courses;//课程
//2.list集合类型属性
private List<String> list;
//3.Map集合类型属性
private Map<String,String> map;
//4.set集合类型属性
private Set<String> set;
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
}
8.在集合里面设置对象类型值
<bean id="student" class="com.ccw.spring5.day05.Student">
<!-- 注入List集合类型,值是对象 -->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<!-- 创建多个course对象 -->
<bean id="course1" class="com.ccw.spring5.day05.Course">
<property name="name" value="Spring5"></property>
</bean>
<bean id="course2" class="com.ccw.spring5.day05.Course">
<property name="name" value="SpringBoot"></property>
</bean>
9.集合注入部分共用
需要在Spring配置文件中引入名称空间util
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
</beans>
使用util标签完成List集合注入提取
<!-- 提取list集合属性注入(公共部分)-->
<util:list id="bookList">
<value>唐诗三百首</value>
<value>伊索寓言</value>
<value>睡前故事</value>
</util:list>
<!-- 公共部分的使用 -->
<bean id="book" class="com.ccw.spring5.day05.Book">
<property name="list" ref="bookList"></property>
</bean>
Book类:
public class Book {
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
public void add(){
System.out.println(list);
}
}
10. Bean的两种类型
分为普通bean工厂bean(FactoryBean)
普通bean:class中的类就是返回值的类型
工厂bean:配置文件定义的bean类型和返回值类型可以不同
步骤:
1.创建类,让这个类作为工厂bean,实现接口FactoryBean
2.实现接口中的方法,在实现的方法中定义返回的bean类型
public class MyBean implements FactoryBean<Course> {//添加泛型为需要的类型
//定义返回bean的类型
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setName("adc");
return course;
}
<!--bean中为工厂类的类名-->
<bean id="myBean" class="com.ccw.spring5.day06.MyBean"></bean>
//测试类中对应的地方也应进行修改
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("BeanXml/day06/bean6.xml");
Course course = context.getBean(/*这里需要填写bean中的id名称*/"myBean",Course.class);
System.out.println(course);
}
11.bean作用域
在spring中,设置创建bean实例是单实例还是多实例(
默认为单实例
)
无论创建多少个对象,都表示同一个地址
那么如何设置多实例呢?
可以在spring配置文件中的bean标签里面的
scope
用来设置scope两个主要的属性值:
singleton:表示单实例对象(默认值)
prototype:表示多实例对象
在bean标签中加入scope属性,那么就变成了多例
两者区别:
当scope为singleton时,在加载spring配置文件时就会创建单实例对象
当scope为prototype时,在调用getbean方法的时候创建多实例对象,而不是在配置spring文件的时候
12.bean的生命周期
什么叫bean生命周期:从对象创建到对象销毁的过程
bean生命周期步骤:
(1)通过构造器创建bean实例(无参数构造)
(2)为bean的属性设置值和对其他bean引用(调用set方法)
(3)调用bean的初始化的方法(需要进行配置初始化的方法)
需要在spring文件中进行添加
![]()
(4) bean可以使用了(对象获取到了)
(5)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
代码如下:
public class Order {
private String name;
//第一步 执行无参构造器创建bean实例
public Order() {
System.out.println("第一步 执行无参构造器创建bean实例");
}
//第二步 调用set方法设置属性值
public void setName(String name) {
this.name = name;
System.out.println("第二步 调用set方法设置属性值");
}
//第三步 创建执行初始化的方法
public void initMethod(){
System.out.println("第三步 创建执行初始化的方法");
}
//第四步 获取创建bean实例对象(写在测试方法中,这里为了方便写在order类中)
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("BeanXml/day07/bean7.xml");
Order order = context.getBean("order",Order.class);
System.out.println(order);
System.out.println("第四步 获取创建bean实例对象");
//手动销毁bean
((ClassPathXmlApplicationContext)context).close();
}
//第五步 执行销毁的方法
public void destroyMethod(){
System.out.println("第五步 创建执行销毁的方法");
}
}
xml文件代码如下:
<bean id="order" class="com.ccw.spring5.day07.Order"
init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="手机"></property>
</bean>
后置处理器
:
也是bean生命周期的步骤,添加进入的顺序为:(添加后为7步)
(1)通过构造器创建bean实例(无参数构造)
(2)为bean的属性设置值和对其他bean引用(调用set方法)
(3) 把bean实例传递bean后置处理器的方法(postProcessBeforeInitialization)
(4)调用bean的初始化的方法(需要进行配置初始化的方法)
(5) 把bean实例传递bean后置处理器的方法(postProcessAfterInitialization)
(6) bean可以使用了(对象获取到了)
(7)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
13.自动装配(自动注入属性)
根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注
<!--
实现自动装配:
bean标签中的autowire,配置自动装配
autowire两个常用属性:
①:byName:根据属性名称注入
②:byType:根据属性类型注入
-->
<!-- 根据名称 -->
<bean id="employee" class="com.ccw.spring5.day08.Employee" autowire="byName"></bean>
<bean id="dept" class="com.ccw.spring5.day08.Department"></bean><!--注入的值要与实现类中属性名称相同 -->
<!-- 根据类型 -->
<bean id="employee" class="com.ccw.spring5.day08.Employee" autowire="byType"></bean>
<bean id="dept" class="com.ccw.spring5.day08.Department"></bean>
<!-- <bean id="dept1" class="com.ccw.spring5.day08.Department"></bean>
使用byType时,相同类型的bean只能定义一个-->
14.引入外部属性文件(等之后理解)
3.2.2 基于注解方式实现
1.注解详解
1.注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值)
2.使用注解时,可以在类上面,方法上面,属性上面
3.使用注解目的:简化xml文件
2.创建对象
分为四种:四种功能相同都可以用来创建bean实例,一般用在对应的地方
@Component(皆可) @Service(业务层,service层) @Controller(web层) @Repository(dao层)
步骤:
1.引入依赖
![]()
2.开启组件扫描
两种方式:1.如果想扫描多个包中的内容,多个包之间只用逗号隔开
2.扫描包的上层目录3.创建类,类上面添加注解(注解中的value可以不写,默认为类名首字母小写)
<?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:p="http://www.springframework.org/schema/p"
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 http://www.springframework.org/schema/context/spring-context.xsd" >
<!-- 开启组件扫描-->
<context:component-scan base-package="com.ccw.annotation.day01"></context:component-scan>
</beans>
组件扫描的两种特殊方式:
<!-- 开启组件扫描-->
<!--方式一 :包含类型为......-->
<context:component-scan base-package="com.ccw.annotation.day01" use-default-filters="false"><!--use-default-filters表示是否需要全部扫描-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--方式二:不包含类型为......-->
<context:component-scan base-package="com.ccw.annotation.day01" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
3.属性注入
常用四种:
@Autowired:根据属性类型进行自动装配
@Qualifier:根据属性名称进行注入,
要和@Autowired一起使用
若@Autowired指明某个接口,但是此接口有多个实现类,那么就需要使用@Qualifier来进行指明
//定义Dao类型属性
//不需要添加set方法,注解自带
@Autowired
@Qualifier(value = "userDaoImpl2")
private UserDao userDao;
@Resource:可以根据类型注入,可以根据名称注入,
括号中的属性为name
@Value:注入普通类型属性
例如String类型
@Value(value = "ccw")//注入属性的值
private String name;
4.完全注解开发
1.创建配置类(xml就可以删除了)
@Configuration //作为配置替换xml配置文件
@ComponentScan(basePackages = {"com.ccw.annotation"})
//相当于xml中的<context:component-scan base-package="com.ccw.annotation" >
public class SpringConfig {
}
2.编写测试类(相当于把以前的测试代码中的 ClassPathXmlApplicationContext 改成AnnotationConfigApplicationContext 其余不变)
public void test(){
//加载配置类
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService",UserService.class);
userService.add();
}