bean的生命周期
- 生命周期:从创建到消亡的完整过程
- bean生命周期:bean从创建到销毁的整体过程
- bean生命周期控制:在bean创建后到销毁前做一些事情
- 具体描述
- 初始化容器
- 创建对象(内存分配)
- 执行构造方法
- 执行属性注入(set操作)
- 执行bean初始化方法
- 使用bean
- 执行业务操作
- 关闭/销毁容器
- 执行bean销毁方法
- 初始化容器
销毁bean的两种方式
-
close()暴力方式
-
registerShutdownHook()
-
public static void main( String[] args ) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); BookDao bookDao = (BookDao) ctx.getBean("bookDao"); bookDao.save(); //注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器 //ctx.registerShutdownHook(); //关闭容器 ctx.close(); }
-
提供生命周期控制方式
-
public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..."); } //表示bean初始化对应的操作 public void init(){ System.out.println("init..."); } //表示bean销毁前对应的操作 public void destory(){ System.out.println("destory..."); } }
-
配置生命周期控制方法
-
<!--init-method:设置bean初始化生命周期回调函数--> <!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象--> <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
依赖注入的两种方式
setter注入
-
简单类型
-
引用类型
-
在bean中定义引用类型属性并提供可访问的set方法
-
public class BookDaoImpl implements BookDao { private String databaseName; private int connectionNum; //setter注入需要提供要注入对象的set方法 public void setConnectionNum(int connectionNum) { this.connectionNum = connectionNum; } //setter注入需要提供要注入对象的set方法 public void setDatabaseName(String databaseName) { this.databaseName = databaseName; } public void save() { System.out.println("book dao save ..."+databaseName+","+connectionNum); } }
-
配置中使用property标签value属性注入简单类型数据
-
<!--注入简单类型--> <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <!--property标签:设置注入属性--> <!--name属性:设置注入的属性名,实际是set方法对应的名称--> <!--value属性:设置注入简单类型数据值--> <property name="connectionNum" value="100"/> <property name="databaseName" value="mysql"/> </bean>
-
构造器注入
-
简单类型
-
引用类型
-
在bean中定义引用类型属性并提供可访问的构造方法
-
public class BookServiceImpl implements BookService{ private BookDao bookDao; private UserDao userDao; public BookServiceImpl(BookDao bookDao, UserDao userDao) { this.bookDao = bookDao; this.userDao = userDao; } public void save() { System.out.println("book service save ..."); bookDao.save(); userDao.save(); } }
-
配置中使用constructor-arg标签ref属性注入引用类型对象
-
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/> <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"> <constructor-arg name="userDao" ref="userDao"/> <constructor-arg name="bookDao" ref="bookDao"/> </bean>
-
配置中使用constructor-arg标签type属性设置按形参类型注入
-
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <!--根据构造方法参数类型注入--> <constructor-arg type="int" value="10"/> <constructor-arg type="java.lang.String" value="mysql"/> </bean>
-
配置中使用constructor-arg标签index属性设置按形参类型注入
-
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <!--根据构造方法参数位置注入--> <constructor-arg index="0" value="mysql"/> <constructor-arg index="1" value="100"/> </bean>
-
依赖注入方式选择
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
依赖自动装配
-
配置中使用bean标签autowire属性设置自动装配的类型
-
<bean class="com.itheima.dao.impl.BookDaoImpl"/> <!--autowire属性:开启自动装配,通常使用按类型装配--> <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
依赖自动装配特征
- 自动装配用于引用类型依赖注入,不能对简单类型进行操作
- 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
- 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
- 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
集合注入
-
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <!--数组注入--> <property name="array"> <array> <value>100</value> <value>200</value> <value>300</value> </array> </property> <!--list集合注入--> <property name="list"> <list> <value>itcast</value> <value>itheima</value> <value>boxuegu</value> <value>chuanzhihui</value> </list> </property> <!--set集合注入--> <property name="set"> <set> <value>itcast</value> <value>itheima</value> <value>boxuegu</value> <value>boxuegu</value> </set> </property> <!--map集合注入--> <property name="map"> <map> <entry key="country" value="china"/> <entry key="province" value="henan"/> <entry key="city" value="kaifeng"/> </map> </property> <!--Properties注入--> <property name="properties"> <props> <prop key="country">china</prop> <prop key="province">henan</prop> <prop key="city">kaifeng</prop> </props> </property> </bean>
第三方配置资源管理
-
导入druid坐标
-
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency>
-
配置数据源对象作为spring管理的bean
-
<!-- 管理DruidDataSource对象--> <bean class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean>
加载properties
-
开启context 命名空间
-
<?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: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"> </beans>
-
使用context命名空间,加载指定properties文件
-
<!--classpath:*.properties : 设置加载当前工程类路径中的所有properties文件--> <!--system-properties-mode属性:是否加载系统属性--> <context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/> <!--classpath*:*.properties : 设置加载当前工程类路径和当前工程所依赖的所有jar包中的所有properties文件-->
-
使用${}读取加载的属性值
-
<!-- 说明:idea自动识别${}加载的属性值,需要手工点击才可以查阅原始书写格式--> <property name="username" value="${jdbc.username}"/>
容器
- 创建容器
- 获取bean
- 容器类层次结构
- BeanFactory
核心容器总结
容器相关
- BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
- ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
- ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展功能
- ApplicationContext接口常用初始化类
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
bean相关
- id,name,class,scope,init-method,destroy-method,autowire,factory-method,factory-bean,lazy-init
依赖注入相关
- constructor-arg name ref
- constructor-arg name value
- constructor-arg type index
- property name ref
- property name value
- property name list
注解开发
注解开发定义bean
-
使用@Component定义bean
-
@Component("bookDao") public class BookDaoImpl implements BookDao { } @Component public class BookServiceImpl implements BookService { }
-
核心配置文件中通过组件扫描加载bean
-
<context:component-scan base-package="com.itheima"/>
-
Spring提供@Component注解的三个衍生注解
- @Controller:用于表现层bean定义
- @Service:用于业务层bean定义
- @Repository:用于数据层bean定义
纯注解开发
-
Spring3.0升级了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发通道
-
Java类代替了Spring核心配置文件
-
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.itheima"/> </beans>
-
//声明当前类为Spring配置类 @Configuration //设置bean扫描路径,多个路径书写为字符串数组格式 @ComponentScan({"com.itheima.service","com.itheima.dao"}) public class SpringConfig { }
-
读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象
-
//加载配置文件初始化容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //加载配置类初始化容器 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
bean作用范围以及生命周期
-
使用@Scope定义bean作用范围
-
使用@PostConstruct、@PreDestroy定义bean生命周期
-
@Repository //@Scope设置bean的作用范围 @Scope("singleton") public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..."); } //@PostConstruct设置bean的初始化方法 @PostConstruct public void init() { System.out.println("init ..."); } //@PreDestroy设置bean的销毁方法 @PreDestroy public void destroy() { System.out.println("destroy ..."); } }
依赖注入(注解版)
自动装配
-
使用@Autowired注解开启自动装配模式(按类型)
-
使用@Qualifier注解开启指定名称装配bean
-
@Service public class BookServiceImpl implements BookService { //@Autowired:注入引用类型,自动装配模式,默认按类型装配 @Autowired //@Qualifier:自动装配bean时按bean名称装配 @Qualifier("bookDao") private BookDao bookDao; //setBookDao已经被去除了 public void save() { System.out.println("book service save ..."); bookDao.save(); } }
-
注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法
-
注意:自动装配建议使用无参构造方法创建对象(默认),如果不提供对应的构造方法,请提供唯一的构造方法
-
注意:@Qualifier注解无法单独使用,必须配合@Autowire注解使用
-
使用@Value实现简单类型注入
-
@Repository("bookDao") public class BookDaoImpl implements BookDao { //@Value:注入简单类型(无需提供set方法) @Value("${name}") private String name; }
-
加载properties文件
-
使用@PropertySource注解加载properties文件
-
注意:路径仅支持单一文件配置,多文件请使用数组格式配置,不允许使用通配符*
-
@Configuration @ComponentScan("com.itheima") //@PropertySource加载properties配置文件 @PropertySource({"jdbc.properties"}) public class SpringConfig { }
-
第三方
bean管理
-
使用@Bean配置第三方bean
-
@Configuration public class SpringConfig { @Bean public DataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; } }
-
将独立的配置类加入核心配置
-
方式一:导入式
-
public class JdbcConfig { @Bean public DataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); //相关配置 return ds; } }
-
使用@Import注解手动加入配置类到核心配置,此注解只能添加一次,多个数据请用数组格式
-
@Configuration @Import(JdbcConfig.class) public class SpringConfig { }
-
将独立的配置类加入核心配置
-
方式二:扫描式
-
@Configuration public class JdbcConfig { @Bean public DataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); //相关配置 return ds; } }
-
使用@ComponentScan注解扫描配置类所在的包,加载对应的配置类信息
-
@Configuration @ComponentScan({"com.itheima.config","com.itheima.service","com.itheima.dao"}) public class SpringConfig { }
bean依赖注入
-
简单类型依赖注入
-
public class JdbcConfig { //1.定义一个方法获得要管理的对象 @Value("com.mysql.jdbc.Driver") private String driver; @Value("jdbc:mysql://localhost:3306/spring_db") private String url; @Value("root") private String userName; @Value("root") private String password; //2.添加@Bean,表示当前方法的返回值是一个bean //@Bean修饰的方法,形参根据类型自动装配 @Bean public DataSource dataSource(BookDao bookDao){ System.out.println(bookDao); DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; } }
-
引用类型依赖注入
-
@Bean public DataSource dataSource(BookService bookService){ System.out.println(bookService); DruidDataSource ds = new DruidDataSource(); //属性设置 return ds; }
-
引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象
注解开发总结
XML配置对比注解配置
Spring整合MyBatis
-
MyBatis程序核心对象分析
-
//初始化SqlSessionFactory // 1. 创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 2. 加载SqlMapConfig.xml配置文件 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml.bak"); // 3. 创建SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); //获取连接,获取实现 // 4. 获取SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 执行SqlSession对象执行查询,获取结果User AccountDao accountDao = sqlSession.getMapper(AccountDao.class); //获取数据层接口 Account ac = accountDao.findById(2); System.out.println(ac); //关闭连接 // 6. 释放资源 sqlSession.close();
-
整合MyBatis
-
//初始化属性数据 <configuration> <properties resource="jdbc.properties"></properties> //初始化类型别名 <typeAliases> <package name="com.itheima.domain"/> </typeAliases> //初始化dataSource <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </dataSource> </environment> </environments> //初始化映射配置 <mappers> <package name="com.itheima.dao"></package> </mappers> </configuration>