Spring框架花式创建Bean的n种方法(小结)

常用的从容器中获取bean实例使用这样的方式:

@Test
	public void test() {
		Persion p = (Persion) ioc.getBean("p1");
		System.out.println(p);
	}

常用的在容器中配置组件使用这样的方式:

	<bean id="p1" class="com.gql.bean.Persion">
		<property name="name" value="张三"></property>
		<property name="age" value="18"></property>
		<property name="email" value="zs@163.com"></property>
		<property name="gender" value="男"></property>
	</bean>

下面的实验介绍一些Spring容器中注册组件对象的其他方法。

实验1:根据bean的类型从ioc容器中获取实例

@Test
	public void test01() {
		Persion p = ioc.getBean(Persion.class);
		System.out.println(p);
	}

这种方法查找的好处是不需要类型转换,但是如果ioc容器中要找的bean有多个,使用这种方法查找就会报错。可以改用下面的方式:

	@Test
	public void test01() {
		Persion p = ioc.getBean("p1", Persion.class);
		System.out.println(p);
	}

实验2:通过有参构造器为bean的属性赋值

需要提前在bean中添加有参构造器,才能进行下面的测试。

	<bean id="p2" class="com.gql.bean.Persion">
		<constructor-arg name="name" value="李四"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="email" value="ls@163.com"></constructor-arg>
		<constructor-arg name="gender" value="男"></constructor-arg>
	</bean>

使用这种有参构造器为bean的属性赋值,可以省略name,但是value的顺序必须与bean中的顺序一致。(若再使用index和type进行索引,可以不按顺序)

通过名称空间为bean赋值:

添加p命名空间标签头:xmlns:p=“http://www.springframework.org/schema/p”

<bean id="p4" class="com.gql.bean.Persion" p:name="小王" p:age="22"
		p:gender="男" p:email="wang@163.com"></bean>

实验3:为各种属性赋值

引用类型、集合类型、级联类型。

如题,给出一个赋值的Bean对象,为其在容器中注册。此时所有复杂的赋值都在property标签体内。

public class Persion {
	private String name;
	private String gender;
	private Integer age;
	private String email;

	private Car car;

	private List<Book> book;

	private Map<String, Object> maps;

	private Properties properties;
	//省略setter与getter方法
}

普通属性赋值:

<!-- 普通属性赋值 -->
		<property name="name" value="张三"></property>
		<property name="gender" value="男"></property>
		<property name="age" value="20"></property>
		<property name="email">
			<null />
		</property>

引用类型赋值:

	<bean id="p1" class="com.gql.bean.Persion">
		<!-- 引用外部bean -->
		<!-- <property name="car" ref="c1"></property> -->
		<!-- 引用内部bean(内部bean不能被获取到) -->
		<property name="car">
			<bean class="com.gql.bean.Car">
				<property name="carName" value="自行车"></property>
				<property name="color" value="黑色"></property>
				<property name="price" value="400"></property>
			</bean>
		</property>
	</bean>

	<bean id="c1" class="com.gql.bean.Car">
		<property name="carName" value="宝马"></property>
		<property name="color" value="白色"></property>
		<property name="price" value="30000"></property>
	</bean>

集合类型赋值:

list

<bean id="p1" class="com.gql.bean.Persion">
		<property name="book">
			<list>
				<bean class="com.gql.bean.Book" p:bookName="西游記" p:author="吴承恩"></bean>
				<ref bean="book01" />
			</list>
		</property>
	</bean>

	<bean id="book01" class="com.gql.bean.Book">
		<property name="bookName" value="水浒传"></property>
		<property name="author" value="施耐庵"></property>
	</bean>

map

<property name="maps">
			<map>
				<entry key="k01" value="v01"></entry>
				<entry key="k02" value="v02"></entry>
				<entry key="k03" value-ref="book01"></entry>
				<entry key="k04">
					<bean class="com.gql.bean.Car">
						<property name="carName" value="捷豹"></property>
						<property name="color" value="红色"></property>
						<property name="price" value="50000"></property>
					</bean>
				</entry>
			</map>
		</property>

properties

	<property name="properties">
			<props>
				<prop key="username">root</prop>
				<prop key="password">123456</prop>
			</props>
		</property>

实验4:通过继承实现bean配置信息的重用

下面的代码中p4继承了p3,需要改动的属性在property标签中修改即可,其余的全部原样继承。

<bean id="p3" class="com.gql.bean.Persion">
		<property name="name" value="张三"></property>
		<property name="age" value="20"></property>
		<property name="gender" value="男"></property>
		<property name="email" value="zs@163.com"></property>
	</bean>

	<bean id="p4" parent="p3">
		<property name="name" value="李四"></property>
	</bean>

实验5:单实例singleton和多实例prototype

单实例singleton 多实例prototype
容器启动时创建好对象并保存在容器中 获取Bean时才会创建这个对象
②调用初始化方法 ②调用初始化方法
容器关闭时调用销毁方法 容器销毁时不调用销毁方法
任何时间获取都是获取之前创建好的那个对象 每次获取都会创建一个新的对象

详情可参照博客:通过工厂创建Bean的三种方式

实验6:创建带有生命周期的Bean

ioc容器中注册的组件:

  • 单实例:容器启动的时候就会创建好,容器关闭也会销毁创建的bean。
  • 多实例:获取的时候才创建。

可以为bean自定义一些生命周期方法,spring在创建或销毁的时候就会调用指定的方法。

(1)单实例Singleton测试

在Book类中创建方法:

package com.gql.bean;
public class Book {
	private String bookName;
	private String author;

	public void myInit() {
		System.out.println("Book的初始化方法...");
	}

	public void myDestory() {
		System.out.println("Book的销毁方法...");
	}

	public Book() {
		super();
		// TODO Auto-generated constructor stub
		System.out.println("Book创建...");
	}
}

在xml中注册组件:

<bean id="book01" class="com.gql.bean.Book" destroy-method="myDestory" init-method="myInit"></bean>

测试:

在ApplicationContext中没有close方法,需要将容器类型转换为ConfigurableApplicationContext 。

public class IoCTest {
	ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("ApplicationContext.xml");

	@Test
	public void test10() {
		System.out.println("容器关闭了");
		ioc.close();
	}
}

(2)多实例prototype测试

只需要改变xml中注册组件为多实例:

<bean id="book01" class="com.gql.bean.Book" destroy-method="myDestory" init-method="myInit" scope="prototype"></bean>

仍然使用上面的方法进行测试:

可以看到容器的创建销毁一系列都没有进行,这是因为多实例在获取bean的时候才创建实例。

多实例测试中增加获取bean:

	@Test
	public void test10() {
		Object bean = ioc.getBean("book01");
		System.out.println(bean);
		System.out.println("容器关闭了");
		ioc.close();
	}

测试结果中,成功创建了实例,但是容器关闭并没有销毁Bean。

实验7:测试Bean的后置处理器

后置处理器有一点代理对象的意思,使用后置处理器,Bean的生命周期变成下面的样子:

容器启动—>后置处理器Before—>初始化方法—>后置处理器After—>容器关闭(调用销毁方法)

不管有没有初始化方法,后置处理器都会默认其有,继续工作。

后置处理器:

package com.gql.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 * 1.编写后置处理器
 * 2.将后置处理器注册在配置文件
 * @author guoqianliang
 *
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

	/**
	 * 初始化前调用
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("Before:" + beanName + "将要调用初始化方法了..." + bean);
		return bean;
	}

	/**
	 * 初始化后调用
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("After:" + beanName + "初始化方法调用完了" + bean);
		return bean;
	}
}

将后置处理器注册在配置文件:

<?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="book01" class="com.gql.bean.Book" destroy-method="myDestory" init-method="myInit" scope="singleton"></bean>

	<!-- 后置处理器:可以在bean的初始化前后调用方法 -->
	<bean id="beanPostProcessor" class="com.gql.bean.MyBeanPostProcessor"></bean>
</beans>

测试:

@Test
	public void test11() {
		Object bean = ioc.getBean("book01");
		System.out.println("容器关闭了");
		ioc.close();
	}

实验8:引用外部文件

在Spring中bean默认都是单实例的,而数据库作为单实例是最好不过的,一个项目就是一个连接池,连接池里面管理很多连接,连接是直接从连接池中拿。可以让Spring帮我们创建连接池对象,管理连接池。

注册连接池第一代

在配置中注册连接池:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="root"></property>
		<property name="password" value="Hudie"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
	</bean>

测试:

@Test
	public void test12() throws SQLException {
		// 从容器中拿到连接
		// DataSource bean = (DataSource) ioc.getBean("dataSource");
		DataSource bean2 = ioc.getBean(DataSource.class);
		System.out.println(bean2.getConnection());
	}

成功获取到了这个连接:

注册连接池第二代

在config包下创建一个dbconfig.properties用来保存数据库连接信息。

为了防止配置文件中的key与Spring自己的关键字冲突。可以为key加一个前缀,业内通用的做法是使用jabc.xxx

jdbc.username:root
jdbc.password:Hudie
jdbc.jdbcUrl:jdbc:mysql://localhost:3306/test
jdbc.driverClass:com.mysql.jdbc.Driver

注册数据库连接池:

	<bean id="dataSource"
		class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<property name="driverClass" value="${jdbc.driverClass}"></property>
	</bean>

测试:

@Test
	public void test12() throws SQLException {
		DataSource bean2 = ioc.getBean(DataSource.class);
		System.out.println(bean2.getConnection());
	}

到此这篇关于Spring框架花式创建Bean的n种方法的文章就介绍到这了,更多相关Spring 创建Bean内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring-Bean创建对象的步骤方式详解

    1.通过无参构造函数创建(默认) 2.通过有参构造创建 1.constructor 的index赋值 <bean id="user" class="com.c.pojo.user"> <constructor-arg index= 0 value=" "> </bean> 2.constructor 的 type 方式: <bean id="user" class="com.

  • JSP 开发之Spring Boot 动态创建Bean

    JSP 开发之Spring Boot 动态创建Bean 1.通过注解@Import导入方式创建 a.新建MyImportBeanDefinitionRegistrar注册中心 Java代码 import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org

  • Spring基于ProxyFactoryBean创建AOP代理

    Spring 通知类型 通过前面的学习可以知道,通知(Advice)其实就是对目标切入点进行增强的内容,Spring AOP 为通知(Advice)提供了 org.aopalliance.aop.Advice 接口. Spring 通知按照在目标类方法的连接点位置,可以分为以下五种类型,如表 1 所示. 表 1 Spring 通知的 5 种类型 名称 说明 org.springframework.aop.MethodBeforeAdvice(前置通知) 在方法之前自动执行的通知称为前置通知,可以

  • Spring如何使用注解的方式创建bean

    这篇文章主要介绍了Spring如何使用注解的方式创建bean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 第一种使用配置类的方式 1.创建一个bean package com.springbean; public class Person { private String name; private Integer age ; public Person(String name, Integer age) { this.name = name

  • Spring工厂方法创建(实例化)bean实例代码

    目标明确 简单叙述一下本文想要解决的问题:如何在Spring中不再使用Spring创建Bean实例,而是把Bean创建过程转移到开发者手中. 思路清晰 创建Bean实例的方式: 1) 通过构造器(有参或无参) 方式: <bean id="" class=""/> 2) 通过静态工厂方法 方式: <bean id="" class="工厂类" factory-method="静态工厂方法"/

  • Spring创建Bean的6种方式详解

    前言 本文讲解了在Spring 应用中创建Bean的多种方式,包括自动创建,以及手动创建注入方式,实际开发中可以根据业务场景选择合适的方案. 方式1: 使用Spring XML方式配置,该方式用于在纯Spring 应用中,适用于简单的小应用,当应用变得复杂,将会导致XMl配置文件膨胀 ,不利于对象管理. <bean id="xxxx" class="xxxx.xxxx"/> 方式2: 使用@Component,@Service,@Controler,@R

  • spring实现bean对象创建代码详解

    我以一个简单的示例解构spring是怎样管理java对象的. 首先,定义一个简单的pojo,代码如下: package com.jvk.ken.spring; public class Demo { private String name; public Demo() { name="I'm Demo."; } public void printName() { System.out.println(name); } public void setName(String name) {

  • 关于Spring中Bean的创建进行更多方面的控制

    我们知道Spring Boot 中一个@Controller修饰的Bean是在什么时间被创建的,那么这个Bean创建时间能不能由我们管控?答案是肯定的 关于Spring中Bean的创建,除了配置装配属性外,我们还可以进行更多方面的控制. 1,首先,我们可以控制Bean是单例还是可以生成多个对象的. 在Spring中,Bean默认是单例的,如果想每次请求都生成一个新的Bean对象,可以在定义Bean时,在<bean>标签中配置scope属性为prototype,那么,就会允许该Bean可以被多次

  • Spring BPP中如何优雅的创建动态代理Bean详解

    v一.前言 本文章所讲并没有基于Aspectj,而是直接通过Cglib以及ProxyFactoryBean去创建代理Bean.通过下面的例子,可以看出Cglib方式创建的代理Bean和ProxyFactoryBean创建的代理Bean的区别. v二.基本测试代码 测试实体类,在BPP中创建BppTestDepBean类型的代理Bean. @Component public static class BppTestBean { @Autowired private BppTestDepBean d

  • Spring Boot如何动态创建Bean示例代码

    前言 本文主要给大家介绍了关于Spring Boot动态创建Bean的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. SpringBoot测试版本:1.3.4.RELEASE 参考代码如下: package com.spring.configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.su

随机推荐