zoukankan      html  css  js  c++  java
  • 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

    1. 导入spring-test-4.3.18.RELEASE.jar
    2. 配置@ContextConfiguration
    3. 配置@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());
    	}
    
    }2
  • 相关阅读:
    redis数据持久化
    redis安全:给redis设置密码
    redis命令总结
    redis事务
    redis发布订阅
    Java中的日期
    链式队列
    删除链表中的结点(链表)、比较含退格的字符串(栈)、棒球比赛(栈)
    物理层
    链式栈
  • 原文地址:https://www.cnblogs.com/wushaopei/p/11762936.html
Copyright © 2011-2022 走看看