Spring IOC容器-Bean管理——基于XML(续集)
IOC 操作 Bean 管理
1、FactoryBean
1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)
2、普通 bean:在配置文件中定义 bean 类型就是返回类型
3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样 第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean 第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class MyBean implements FactoryBean<Course> {
@Override public Course getObject() throws Exception { Course course = new Course(); course.setCname("abc"); return course; } } <bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean"> </bean> @Test public void test3() { ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml"); Course course = context.getBean("myBean", Course.class); System.out.println(course); }
|
2、bean 作用域
在 Spring 里面,默认情况下,bean 是单实例对象,下面进行作用域设置:
- 在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
- scope 属性值 第一个值 默认值,singleton,表示是单实例对象 第二个值 prototype,表示是多实例对象
1 2 3
| <bean id="book" class="com.atguigu.spring5.collectiontype.Book" scope="prototype"> <property name="list" ref="bookList"></property> </bean>
|
- singleton 和 prototype 区别
- singleton 单实例,prototype 多实例
- 设置 scope 值是 singleton 时候, 加载 spring 配置文件时候就会创建单实例对象 ;
- 设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建对象,在调用 getBean 方法时候创建多实例对象
3、bean 生命周期
1 ) 生命周期 :
2 ) bean 生命周期
- 通过构造器创建 bean 实例(无参数构造)
- 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
- 调用 bean 的初始化的方法(需要进行配置初始化的方法)
- bean 可以使用了(对象获取到了)
- 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
3 ) 演示 bean 生命周期 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Orders { public Orders() { System.out.println("第一步 执行无参数构造创建 bean 实例"); } private String oname; public void setOname(String oname) { this.oname = oname; System.out.println("第二步 调用 set 方法设置属性值"); } public void initMethod() { System.out.println("第三步 执行初始化的方法"); } public void destroyMethod() { System.out.println("第五步 执行销毁的方法"); } }
|
创建类实现 BeanPostProcessor
接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class MyBeanPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("在初始化之前执行的方法"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("在初始化之后执行的方法"); return bean; } } <!--配置文件的bean参数配置--> <bean id="orders" class="com.atguigu.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"> <!--配置初始化方法和销毁方法--> <property name="oname" value="手机"></property><!--这里就是通过set方式(注入属性)赋值--> </bean>
<!--配置后置处理器--> <bean id="myBeanPost" class="com.atguigu.spring5.bean.MyBeanPost"></bean> @Test public void testBean3() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml"); Orders orders = context.getBean("orders", Orders.class); System.out.println("第四步 获取创建 bean 实例对象"); System.out.println(orders); context.close(); }
|
4 ) bean 的后置处理器
bean 生命周期有七步(正常生命周期为五步,而配置后置处理器后为七步)
- 通过构造器创建 bean 实例(无参数构造)
- 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
- 把 bean 实例传递 bean 后置处理器的方法
postProcessBeforeInitialization
- 调用 bean 的初始化的方法(需要进行配置初始化的方法)
- 把 bean 实例传递 bean 后置处理器的方法
postProcessAfterInitialization
- bean 可以使用了(对象获取到了)
- 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
4、xml自动装配Bean
自动装配的配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?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.xsd">
<bean id="emp" class="com.Keafmd.spring5.autowire.Emp" autowire="byType">
</bean>
<bean id="dept" class="com.Keafmd.spring5.autowire.Dept"></bean>
</beans>
|
测试代码相同:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import com.Keafmd.spring5.autowire.Emp; import com.Keafmd.spring5.bean.Orders; import com.Keafmd.spring5.collectiontype.Book; import com.Keafmd.spring5.collectiontype.Course; import com.Keafmd.spring5.collectiontype.Stu; import com.Keafmd.spring5.factorybean.MyBean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5demo1 { @Test public void test5(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml"); Emp emp = context.getBean("emp",Emp.class); System.out.println(emp);
} }
|
测试结果:
Emp{dept=Dept{}}
这就是自动装配,但是这种基于xml自动装配并不常用,常用的是基于注解的。
以上就是基于xml的自动装配。
5、外部属性文件
- 方式一:直接配置数据库信息 :(1)配置Druid(德鲁伊)连接池 (2)引入Druid(德鲁伊)连接池依赖 jar 包
1 2 3 4 5 6 7 8
| <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean>
|
- 方式二:引入外部属性文件配置数据库连接池
- 创建外部属性文件,properties 格式文件,写数据库信息(
jdbc.properties
)
1 2 3 4
| prop.driverClass=com.mysql.cj.jdbc.Driver prop.url=jdbc:mysql://localhost:3306/userDb prop.userName=root prop.password=qwer
|
2. 把外部 properties 属性文件引入到 spring 配置文件中 —— 引入 context 名称空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${prop.driverClass}"></property> <property name="url" value="${prop.url}"></property> <property name="username" value="${prop.userName}"></property> <property name="password" value="${prop.password}"></property> </bean> </beans>
|
IOC 操作 Bean 管理(基于注解方式)
1、什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化 xml 配置
2、Spring 针对 Bean 管理中创建对象提供注解
Component 组成部分;成分;部件 [kəmˈpoʊnənt]
Repository 仓库;资源库;版本库;知识库 [rɪˈpɑːzətɔːri]
下面四个注解**==功能是一样的==**,都可以用来创建 bean 实例
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
注解 |
说明 |
@Component |
使用在类上用于实例化Bean |
@Controller |
使用在web层类上用于实例化bean |
@Service |
使用在service用于实例化bean |
@Repository |
使用在dao层类上用于实例化bean |
3、⭐基于注解方式实现对象建
第一步 引入依赖 (引入spring-aop jar包)
第二步 开启组件扫描
下面的这种扫描方式会扫描这个包下的所有类
1 2 3 4 5
|
<context:component-scan base-package="com.atguigu"></context:component-scan>
|
第三步 创建类,在类上面添加创建对象注解
-
value属性值可以不写
- 默认是类的名称的首字母小写 : 例如这里 UserService — 》 userService
1 2 3 4 5 6 7
| @Component(value = "userService")
public class UserService { public void add() { System.out.println("service add......."); } }
|
4、开启组件扫描细节配置
生词:
annotation: 注释, 注解 [ˌænəˈteɪʃn]
exclude : 排除 把…排斥在外;认为…不可能 [ɪkˈskluːd]
-
use-default-filters="false"
表示现在不使用默认 filter
,自己配置 filter
context:include-filter
设置扫描哪些内容
例如下面的配置文件就是使Spring只扫描使用Controller注解的类
1 2
| <context:component-scan base-package="com.atguigu" use-defaultfilters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
|
-
表示Controller注解的类之外一切都进行扫描
1 2
| <context:component-scan base-package="com.atguigu"> <context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/>
|
5、基于注解方式实现属性注入
生词:
autowired :自动装配
qualifier : (击败对手可进入某竞赛的)合格者;预选赛;资格赛;外围赛;修饰词(尤指形容词或副词) [ˈkwɑːlɪfaɪər]
1)@Autowired
第一步
- 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解
第二步
- 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解
1 2 3 4 5 6 7 8 9 10 11 12
| @Service public class UserService { @Autowired private UserDao userDao; public void add() { System.out.println("service add......."); userDao.add(); } }
|
1 2 3 4 5 6 7
| @Repository(value = "userDaoImpl") public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("dao add....."); } }
|
2)@Qualifier
1 2 3 4 5 6 7
|
@Autowired @Qualifier(value = "userDaoImpl") private UserDao userDao;
|
3)@Resource
- 可以根据类型注入,也可以根据名称注入(它属于javax包下的注解,⚠️不推荐使用!)
1 2 3 4
| @Resource(name = "userDaoImpl") private UserDao userDao;
|
4)@Value
1 2
| @Value(value = "abc") private String name
|
总体代一览
UserDao.java
1 2 3 4 5 6
| package com.atguigu.spring5.dao;
public interface UserDao { public void add(); }
|
UserDaoImpl.java
1 2 3 4 5 6 7 8 9 10 11 12
| package com.atguigu.spring5.dao.Impl;
import com.atguigu.spring5.dao.UserDao; import org.springframework.stereotype.Repository;
@Repository(value = "userDaoImpl") public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("DAO add....."); } }
|
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.atguigu.spring5.service;
import com.atguigu.spring5.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service public class UserService { @Value(value = "abc") private String name;
@Resource(name = "userDaoImpl") private UserDao userDao;
public void add() { System.out.println("service add......."+name); userDao.add(); } }
|
TestSpring5Demo1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.atguigu.spring5.testdemo;
import com.atguigu.spring5.config.SpringConfig; import com.atguigu.spring5.service.UserService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5Demo1 { @Test public void testService1() { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); userService.add(); } @Test public void testService2() { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); userService.add(); } }
|
读取注解创建容器
不用配置文件, 全部使用注解替代
1)创建配置类,替代 xml 配置文件
- 类名随便起名 ( ==要遵守开发规范== ) ,但是配置类一定要@Configuration 注解 ,表明这是一个配置类
1 2 3 4 5 6
| @Configuration @ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}
|
2)编写测试类
在创建 ApplicationContext 接口实现对象 时, 调用的构造器是 AnnotationConfigApplicationContext 类的构造器
ApplicationContext :interface
常用实现类:
ClassPathXmlApplicationContext : 可以加载类路径下的配置文件 ,要求配置文件必须在类路径下面
AnnotationConfigApplicationContext :读取注解创建容器
1 2 3 4 5 6 7 8 9 10 11
| @Test public void testService2() { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService = context.getBean("userService",UserService.class); System.out.println(userService); userService.add(); }
|