Spring ( 三 ) Spring的Bean的装配与生命周期、专用测试
个人博客网:https://wushaopei.github.io/ (你想要这里多有)
一、对象的生命周期
1、IOC之Bean的生命周期
创建带有生命周期方法的bean
public class Person {
	private Integer id;
	private Car car;
	public void init() {
		System.out.println("Person被初始化了……");
	}
	public void destroy() {
		System.out.println("Person被销毁了");
	}
配置信息:
        <!--
		init-method="init" 		表示初始化方法为init	(在构造器调用之后就调用)
		destroy-method="destroy"	表示销毁方法为destroy(在容器销毁的时候,就调用。只是单例有效)
	 -->
	<bean id="personLife" class="com.webcode.pojo.Person" init-method="init" destroy-method="destroy">
		<property name="id" value="10" />
	</bean>加载结果图解:

2、Bean的后置处理器BeanPostProcessor
bean的后置处理器可以在bean对象调用初始化方法之前和之后做一些工作。
如何创建一个后置处理器呢,只需要实现BeanPostProcessor接口
测试bean的后置处理器
public class MyBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessAfterInitialization(Object bean, String id) throws BeansException {
		System.out.println("初始化方法之后调用 bean=>" + bean + ", id=>" + id);
		if ("personLife".equals(id)) {
			Person person = (Person) bean;
			person.setCar(new Car("你想啥!", "想干啥干啥"));
		}
		return bean;//一定要把bean返回
	}
	@Override
	public Object postProcessBeforeInitialization(Object bean, String id) throws BeansException {
		System.out.println("初始化方法之前调用 bean=>" + bean + ", id=>" + id);
		return bean;//一定要把bean返回
	}
}配置信息:
        <!--
		init-method="init" 		表示初始化方法为init	(在构造器调用之后就调用)
		destroy-method="destroy"	表示销毁方法为destroy(在容器销毁的时候,就调用。只是单例有效)
	 -->
	<bean id="personLife" class="com.webcode.pojo.Person" init-method="init" destroy-method="destroy">
		<property name="id" value="10" />
	</bean>
	<!-- 配置bean的后置处理器 -->
	<bean class="com.webcode.postprocessor.MyBeanPostProcessor" />测试代码:
	@Test
	public void test3() throws Exception {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		System.out.println( applicationContext.getBean("personLife") );
		applicationContext.close();
	}
工作流程图解:

二、Spring管理数据库连接池
前提:导入数据库连接池的jar包


1、Spring配置管理数据库连接池对象(重点)
创建 dataSource.xml 配置文件
配置bean
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="root" />
		<property name="password" value="root" />
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test" />
		<property name="driverClass" value="com.mysql.jdbc.Driver" />
	</bean>
2、Spring引入单独的jdbc.properties配置文件(重点)
PropertyPlaceholderConfigurer
jdbc.properties配置文件:
jdbc.user=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.driverClass=com.mysql.jdbc.Driver容器配置文件:
        <!--
		PropertyPlaceholderConfigurer专门用来加载属性配置文件
	 -->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<!-- 你加载的文件路径在哪
				classpath: 表示从类路径下加载
		 -->
		<property name="location" value="classpath:jdbc.properties"/>
	</bean>
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${jdbc.user}" />
		<property name="password" value="${jdbc.password}" />
		<property name="jdbcUrl" value="${jdbc.url}" />
		<property name="driverClass" value="${jdbc.driverClass}" />
	</bean>打印结果——图解:

3、使用context名称空间加载jdbc.properties配置文件(重点)

        <!-- 使用Context名称空间,加载jdbc.properties -->
	<context:property-placeholder location="classpath:jdbc.properties"/>
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${jdbc.user}" />
		<property name="password" value="${jdbc.password}" />
		<property name="jdbcUrl" value="${jdbc.url}" />
		<property name="driverClass" value="${jdbc.driverClass}" />
	</bean>结果打印图解:

三、注解功能
1、注解配置Dao、Service、Controller组件
通过注解分别创建Dao、Service、Controller
Spring配置bean的常用注解有
- @Controller 配置web层组件
- @Service 配置业务层Service组件
- @Repository 配置持久层Dao组件
- @Component 配置除了web层,Service层,Dao层之外的其他组件bean对象
- @Scope 配置作用域
导包:
commons-logging-1.1.3.jar
spring-aop-4.3.18.RELEASE.jar
spring-beans-4.3.18.RELEASE.jar
spring-context-4.3.18.RELEASE.jar
spring-core-4.3.18.RELEASE.jar
spring-expression-4.3.18.RELEASE.jar工程:

/**
 * @Component
 * 等价于:
 * <bean id="book" class="com.webcode.pojo.Book" />
 */
@Scope("prototype")//多例
//@Scope("singleton")//单例
@Component
public class Book {}单例:

多例:

/**
 * @Repository
 * 	等价于:
 * <bean id="bookDao" class="com.webcode.dao.BookDao" />
 */
@Repository("bookDao")
public class BookDao {
}
/**
 * @Controller
 * 等价于:
 * <bean id="bookServlet" class="com.webcode.servlet.BookServlet" />
 */
@Controller
public class BookServlet {}/**
 * @Service
 * 	等价于:
 * <bean id="bookService" class="com.webcode.service.BookService" />
 */
@Service
public class BookService {}测试的代码:
	@Test
	public void test1() throws Exception {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		System.out.println( applicationContext.getBean("book") );
		System.out.println( applicationContext.getBean("bookDao") );
		System.out.println( applicationContext.getBean("bookService") );
		System.out.println( applicationContext.getBean("bookServlet") );
	}流程分析:

2、指定扫描包时的过滤内容
使用context:include-filter指定扫描包时要包含的类
使用context:exclude-filter指定扫描包时不包含的类
<context:include-filter /> 设置包含的内容
注意:通常需要与use-default-filters属性配合使用才能够达到“仅包含某些组件”这样的效果。即:通过将use-default-filters属性设置为false,
<context:exclude-filter /> 设置排除的内容
| 类别 | 示例 | 说明 | 
| annotation | com.webcode.XxxAnnotation | 过滤所有标注了XxxAnnotation的类。这个规则根据目标组件是否标注了指定类型的注解进行过滤 | 
| assignable | com.webcode.BaseXxx | 过滤所有BaseXxx类的子类。这个规则根据目标组件是否是指定类型的子类的方式进行过滤。 | 
| aspectj | com.webcode.*Service+ | 所有类名是以Service结束的,或这样的类的子类。这个规则根据AspectJ表达式进行过滤。 | 
| regex | com\.webcode\.anno\.* | 所有com.webcode.anno包下的类。这个规则根据正则表达式匹配到的类名进行过滤。 | 
| custom | com.webcode.XxxTypeFilter | 使用XxxTypeFilter类通过编码的方式自定义过滤规则。该类必须实现org.springframework.core.type.filter.TypeFilter接口 | 
applicationContext.xml 中配置的内容如下
<!-- use-default-filters="false" 设置取消默认包含规则 -->
	<context:component-scan base-package="com.webcode" use-default-filters="false">
		<!-- context:include-filter 设置包含的内容 -->
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
		<!-- context:exclude-filter 设置排除的内容 -->
		<context:exclude-filter type="assignable" expression="com.webcode.service.BookService"/>
	</context:component-scan>以上配置会包含所有@Service注解的类。排除com.webcode.service.BookService类
<!--
		配置包扫描。扫描指定包名下(和子包下所有的组件)
			base-package 包名
			use-default-filters="true" 默认扫描 @Repository,Service,Controller,Compoment
	 -->
	<context:component-scan base-package="com.webcode" use-default-filters="false">
		<!--
			context:exclude-filter扫描时排除哪些内容
				type 按哪个类型进行过滤
					annotation按注解进行过滤
				expression表达式
					不要这个注解的org.springframework.stereotype.Repository组件对象
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
		<context:exclude-filter type="assignable" expression="com.webcode.service.BookService"/>
		 -->
		 <!--
		 	context:include-filter	自定义包含一定要组合use-default-filters="false" 一起使用。
		  -->
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
		<context:include-filter type="assignable" expression="com.webcode.service.BookService"/>
	</context:component-scan>3、使用注解@Autowired自动装配
使用@Autowired注解实现根据类型实现自动装配
@Autowired 注解 会自动的根据标注的对象类型在Spring容器中查找相对应的类。如果找到,就自动装配。
使用@Autowired注解,不需要get/set方法
@Service
public class BookService {
	/**
	 * @Autowired注解可以实现自动注入<br/>
	 * 	1 先按类型进行查找注入<br/>
	 *  2 如果找到多个,就按属性名做为id接着查找注入。<br/>
	 */
	@Autowired
	private BookDao bookDao;
	@Override
	public String toString() {
		return "BookService [bookDao=" + bookDao + "]";
	}
}4、多个同类型的bean如何自动装配
如果资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配★
/**
 * @Repository
 * 	等价于:
 * <bean id="bookDao" class="com.webcode.dao.BookDao" />
 */
@Repository("bookDao")
public class BookDao {
}
/**
 * @Repository
 * 	等价于:
 * <bean id="bookDao" class="com.webcode.dao.BookDao" />
 */
@Repository
public class BookDaoExt extends BookDao{
}/**
 * @Service 等价于:
 *          <bean id="bookService" class="com.webcode.service.BookService" />
 */
@Service
public class BookService {
	/**
	 * @Autowired注解可以实现自动注入<br/>
	 * 	1 先按类型进行查找注入<br/>
	 *  2 如果找到多个,就按属性名做为id接着查找注入。<br/>
	 */
	@Autowired
	private BookDao bookDao;
	@Override
	public String toString() {
		return "BookService [bookDao=" + bookDao + "]";
	}
}
打印图解:

5、使用@Qualifier装配指定id的bean对象
如果根据成员变量名作为id还是找不到bean,可以使用@Qualifier注解明确指定目标bean的id★
@Service
public class BookService {
	/**
	 * @Autowired注解可以实现自动注入<br/>
	 * 	1 先按类型进行查找注入<br/>
	 *  2 如果找到多个,就按属性名做为id接着查找注入。<br/>
	 *  3 如果没有找到要报错<br/>
	 *  4 @Qualifier("bookDao")限定你用什么做为id来进行查找注入<br/>
	 */
	@Autowired
	@Qualifier("bookDaoExt")
	private BookDao bookDao;
	@Override
	public String toString() {
		return "BookService [bookDao=" + bookDao + "]";
	}
}6、@Autowired注解的required属性作用
@Autowired注解的required属性指定某个属性允许不被设置
@Service
public class BookService {
	/**
	 * @Autowired注解可以实现自动注入<br/>
	 * 	1 先按类型进行查找注入<br/>
	 *  2 如果找到多个,就按属性名做为id接着查找注入。<br/>
	 *  3 如果没有找到要报错<br/>
	 *  4 @Qualifier("bookDao")限定你用什么做为id来进行查找注入<br/>
	 *  5 你可以修改@Autowired的required属性值为false,允许值为null<br/>
	 */
	@Autowired(required=false)
	@Qualifier("bookDaoExt")
	private BookDao bookDao;
	@Override
	public String toString() {
		return "BookService [bookDao=" + bookDao + "]";
	}
}7、@Autowired和@Qualifier在方法上的使用
在方法的形参位置使用@Qualifier注解
	/**
	 * @Autowired标注在方法上。那么对象创建的时候。会自动调用做初始化工作
	 */
	@Autowired(required=false)
	public void abc(@Qualifier("bookDao1234") BookDao bookDaoExt12) {
		System.out.println("abc执行了 --->>>" + bookDaoExt12);
	}8、泛型注入
测试泛型依赖注入

四、Spring的专有测试
@ContextConfiguration
@RunWith
- 导入spring-test-4.3.18.RELEASE.jar
- 配置@ContextConfiguration
- 配置@RunWith
//@ContextConfiguration(locations="classpath:applicationContext.xml")
// 告诉spring的扩展的测试,说,上哪里去找这个Spring容器的配置文件
@ContextConfiguration(locations="classpath:applicationContext.xml")
// 使用Spring扩展的运行类去跑测试
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest2 {
	@Autowired
	UserService userService;
	@Autowired
	BookService bookService;
	@Test
	public void test() throws Exception {
		userService.saveEntity(new User());
		System.out.println("==================华丽的分隔线=================");
		bookService.saveEntity(new Book());
	}
}2Spring ( 三 ) Spring的Bean的装配与生命周期、专用测试的更多相关文章
- 五 Spring的配置:Bean的配置,生命周期和作用范围
		Bean相关的配置: <bean>标签的id和name的配置: id:使用了约束中的唯一约束,里面不能出现特殊字符 name:没有使用唯一约束,理论上可以重复,实际上开发不行,里面可以出现 ... 
- Spring中Bean的作用域、生命周期
		Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ... 
- Spring之Bean的作用域与生命周期
		在前面博客中提到容器启动获得BeanDefinition对象中有一个scope 属性.该属性控制着bean对象的作用域.本章节介绍Bean的作用域及生命周期,了解bean是怎么来的又怎么没的. 一.B ... 
- 详解Spring中Bean的作用域与生命周期
		摘要:在利用Spring进行IOC配置时,关于bean的配置和使用一直都是比较重要的一部分,同时如何合理的使用和创建bean对象,也是小伙伴们在学习和使用Spring时需要注意的部分,所以这一篇文章我 ... 
- bean的作用域和生命周期
		一.Bean作用域 二.生命周期 其中,这个类实现各种接口重写各种方法,会按bean的声明周期按序执行: 其中,自定义的初始化和自定义销毁的方法不是实现接口重写,而是成员方法,并且在装配bean即在x ... 
- @Scope注解设置创建bean的方式和生命周期
		1.1.1 Scope注解创建bean的方式和生命周期 作用 Scope设置对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式. 取 ... 
- 三张图片详解Asp.Net 全生命周期
		用三张图片详解Asp.Net 全生命周期 下面我们使用三张图片解析ASP.net的整个生命周期,我总感觉使用图片更加的清楚的说明这种问题,所以使用的这样方式 说明: 1 第一张图片从全局说明从客户端 ... 
- Spring三种实例化Bean的方法
		1.实例化bean的三种方法:(1) 构造器<!-- 体验1 --><bean id="personService" class="com.persia ... 
- Spring MVC系列-(2) Bean的装配
		2. Bean的装配 Spring容器负责创建应用程序中的bean,并通过DI来协调对象之间的关系.Spring提供了三种主要的装配机制: XML显式配置: Java配置类进行显式配置: 隐式的bea ... 
随机推荐
- mysql优化–explain分析sql语句执行效率
			Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优 ... 
- Nacos下动态路由配置
			前言 Nacos最近项目一直在使用,其简单灵活,支持更细粒度的命令空间,分组等为麻烦复杂的环境切换提供了方便:同时也很好支持动态路由的配置,只需要简单的几步即可.在国产的注册中心.配置中心中比较突出, ... 
- 图数据库 Nebula Graph 是什么
			图数据库(英语:Graph Database)是一个使用图结构进行语义查询的数据库.该系统的关键概念是图,形式上是点 (Node 或者 Vertex) 和边 (Edge 或者 Relationship ... 
- [hdu5225]逆序对统计
			题目:给定一个1到n的排列,求字典序小于这个排列的所有排列的逆序对数之和. 思路:既然是求字典序小于这个排列的,不妨将排列根据和它前k位相同来分类,然后枚举第k+1位的数(小于原序列第k+1位的数), ... 
- 关于C语言的位运算符
			早期cpu架构在运行位运算时 略微领先 + - 运算 大幅领先 * / % 运算 '&' 运算符 总结 两个二进制中对应的位置都为 1 结果的对应二进制为 1 '&'运算符可以用到奇偶 ... 
- mysql连表查空,查询第二张表中没有第一张表中的数据
			select consumer_id,user_name,mobile,invite_code from csr_consumer where invite_count<(select coun ... 
- 黑马程序员_毕向东_Java基础视频教程——进制的相互转换(随笔)
			进制的相互转换 二进制转十进制: 原理对十进制数进行除2运算(余数不是0 就是1) 6 的二进制: 6 / 2 = 3--0 3 / 2 = 1--1 1 / 2 = 0--1 余数倒序排列输出:11 ... 
- java 多线程详细笔记(原理理解到全部使用)
			鸽了好久以后终于又更新了,看同学去实习都是先学源码然后修改之类,才发觉只是知道语法怎么用还远远不够,必须要深入理解以后不管是学习还是工作,才能举一反三,快速掌握. 目录 基础知识 进程与线程 线程原子 ... 
- js 前端实现文件流下载的几种方式
			后端是用Java写的一个下载的接口,返回的是文件流,需求:点击,请求,下载 利用iframe实现文件流下载 //把上一次创建的iframe删掉,不然随着下载次数的增多页面上会一堆的iframe var ... 
- Js运算符和逻辑结构
			1.运算符 (1)赋值运算符 = += -= *= /= %= (2)三目运算符 一目 一个运算符连接一个数据 -- ++ ! 二目 一个运算符连接两个数据 + - * / ... 
