先说一下Java Bean的概念:
JavaBean其实就是按照一种规范书写的代表实体的Java类。名称中的“Bean”是用于Java的可重用软件组件的惯用叫法。
规范严格意义上需要有一下四点:1)属性私有,2)提供getset方法(public声明,命名符合规范)操作私有属性,3)提供一个无参构造函数,4)实现了Serializable接口。
这些特点使它们有更好的封装性和可重用性。并且可以被序列化(持久化),保存在硬盘或者在网络上传输。
而Spring Bean可以理解成Spring中的Bean,或者说是Spring中的类,而我们可以对这些Bean进行实例化,也就是定义对象。
Spring里面的bean就类似是定义的一个组件,而这个组件的作用就是实现某个功能的,在spring里给定义的bean就是说,我给你了一个更为简便的方法来调用这个组件去实现你要完成的功能。
Spring Bean是事物处理组件类和实体类(POJO)对象的总称,Spring Bean被Spring IOC容器初始化,装配和管理。
Spring工厂类的创建:
1、BeanFactory和ApplicationContext创建实例的时机不同:前者是在工厂实例化完以后,在调用getBean的时候,才会来创建类的实例,而后者是一加载配置文件的时候就会将配置文件中所有单例模式生成的类全都实例化。
2、ClassPathXmlApplicationContext:类路径下的配置文件
FileSystemXmlApplicationContext: 加载文件系统中的配置文件
3、更多时候使用的是ApplicationContext接口以及他的实现类ClassPathXmlApplicationContext和FileSystemXmlApplicationContext来完成Spring工厂类的创建
/*SpringDemo1.java*/
@Test
/*
ClassPathXmlApplicationContext方式实现
*/
public void demo2(){
//创建Spring的工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获得类:
UserService userService = (UserService) applicationContext.getBean("userService");
userService.sayHello();
}
@Test
/**
* 读取磁盘系统中的配置文件,FileSystemXmlApplicationContext
*/
public void demo3(){
//创建Spring的工厂类
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("d:\\applicationContext.xml");
//通过工厂获得类:
UserService userService = (UserService) applicationContext.getBean("userService");
userService.sayHello();
}
/**
* Bean的实例化的三种方式:采用无参数的构造方法的方式
*/
public class Bean1 {
public Bean1(){
System.out.println("Bean1被实例化了...");
}
}
applicationContext.xml:配置id、类
<!--第一种:无参构造器的方式-->
<bean id="bean1" class="com.linmin.ioc.demo2.Bean1"/>
/*SpringDemo2.java*/
@Test
public void demo1(){
// 创建工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂获得类的实例:
Bean1 bean1 = (Bean1)applicationContext.getBean("bean1");
}
/**
* Bean的实例化三种方式:静态工厂实例化方式
*/
public class Bean2 {
}
创建工厂方法:
/**
* Bean2的静态工厂
*/
public class Bean2Factory {
public static Bean2 createBean2(){
System.out.println("Bean2Factory的方法已经执行了...");
return new Bean2();
}
}
applicationContext.xml:配置id、工厂类、工厂方法(factory-method属性)
可以直接调用类的静态方法,不用实例化。
<!--第二种:静态工厂的方式-->
<bean id="bean2" class="com.linmin.ioc.demo2.Bean2Factory" factory-method="createBean2"/>
/*SpringDemo2.java*/
@Test
public void demo2(){
// 创建工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂获得类的实例:
Bean2 bean2 = (Bean2)applicationContext.getBean("bean2");
}
/**
* Bean的实例化三种方式:实例工厂实例化
*/
public class Bean3 {
}
/**
* Bean3的实例工厂
*/
public class Bean3Factory {
public Bean3 createBean3(){
System.out.println("Bean3Factory执行了...");
return new Bean3();
}
}
类中的方法是非静态的,想要调用该方法须先创建一个类对象,再通过对象调用方法。
<!--第三种:实例工厂的方式
配置两个bean:
一个配置id、工厂类
一个配置id、工厂id(factory-bean属性)、工厂类方法(factory-method属性)-->
<bean id="bean3Factory" class="com.linmin.ioc.demo2.Bean3Factory"/>
<bean id="bean3" factory-bean="bean3Factory" factory-method="createBean3"/>
/*SpringDemo2.java*/
@Test
public void demo3(){
// 创建工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂获得类的实例:
Bean3 bean3 = (Bean3)applicationContext.getBean("bean3");
}
一般情况下采用第一种方式,当构造比较复杂时采用二三种方法
<bean id="bean1" class="com.linmin.ioc.demo2.Bean1"/>
1、一般情况下,装配一个Bean时,通过指定一个id属性作为Bean的名称,id属性在IOC容易中必须是唯一的,如果Bean的名称中含有特殊字符,就需要使用name属性
<bean name="bean1/" class="com.linmin.ioc.demo2.Bean1"/>
2、class用于设置一个类的完全路径名称,主要作用是IOC容器生成类的实例
类别 | 说明 |
---|---|
singleton(默认值) | 在SpringIOC容器中仅存在一个Bean实例,Bean以单实例的方式存在 |
prototype | 每次调用getBean()时都会返回一个新的实例(多例) |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同的HTTP Session使用不同的Bean。该作用域仅适用于WebApplicationContext环境 |
1、singleton:
<bean id="person" class="com.linmin.ioc.demo3.Person" scope="singleton"/>
此时的scope可以不写,默认即为singleton。
/*SpringDemo3.java*/
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person persion1 = (Person)applicationContext.getBean("person");
Person persion2 = (Person)applicationContext.getBean("person");
System.out.println(persion1);
System.out.println(persion2);
}
此时输出的persion1和persion2地址一样,说明为单例模式。
2、prototype:
<bean id="person" class="com.linmin.ioc.demo3.Person" scope="prototype"/>
/*SpringDemo3.java*/
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person persion1 = (Person)applicationContext.getBean("person");
Person persion2 = (Person)applicationContext.getBean("person");
System.out.println(persion1);
System.out.println(persion2);
}
此时输出的persion1和persion2地址不一样,说明为多例模式。
public class Man{
public Man(){
System.out.println("MAN被实例化了...");
}
public void setup(){
System.out.println("MAN被初始化了...");
}
public void teardown(){
System.out.println("MAN被销毁了...");
}
}
<bean id="man" class="com.linmin.ioc.demo3.Man" init-method="setup" destroy-method="teardown">
/*SpringDemo3.java*/
@Test
public void demo2(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Man man = (Man)applicationContext.getBean("man");
applicationContext.close();
}
1、instantiate bean对象实例化
2、populate properties 封装属性
3、如果Bean实现BeanNameAware执行setBeanName
4、如果Bean实现BeanFactoryAware或者ApplicationContextAware 设置工厂setBeanFactory或者上下文对象setApplicationContext
5、如果存在类实现BeanPostProcessor (后处理Bean) , 执行postProcessBeforeInitialization
6、如果Bean实现InitializingBean执行afterPropertiesSet
7、调用< bean init-method= “init”>指定初始化方法init
8、如果存在类实现BeanPostProcessor (处理Bean),执行postProcessAfterInitialization
9、执行业务处理
10、如果Bean实现DisposableBean执行destroy
11、调用< bean destroy-method= “customerDestroy”>指定销毁方法customerDestroy
public class Man implements BeanNameAware,ApplicationContextAware,InitializingBean,DisposableBean{
private String name;
public void setName(String name) {
System.out.println("第二步:设置属性");
this.name = name;
}
public Man(){
System.out.println("第一步:初始化...");
}
public void setup(){
System.out.println("第七步:MAN被初始化了...");
}
public void teardown(){
System.out.println("第十一步:MAN被销毁了...");
}
@Override
public void setBeanName(String name) {
System.out.println("第三步:设置Bean的名称"+name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("第四步:了解工厂信息");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("第六步:属性设置后");
}
public void run(){
System.out.println("第九步:执行业务方法");
}
@Override
public void destroy() throws Exception {
System.out.println("第十步:执行Spring的销毁方法");
}
}
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步:初始化前方法...");
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("第八步:初始化后方法...");
return bean;
}
}
<bean id="man" class="com.linmin.ioc.demo3.Man" init-method="setup" destroy-method="teardown">
<property name="name" value="张三"/>
</bean>
<bean class="com.linmin.ioc.demo3.MyBeanPostProcessor"/>
/*SpringDemo3.java*/
@Test
public void demo2(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Man man = (Man)applicationContext.getBean("man");
man.run();
applicationContext.close();
}
public class User {
private String name;
private Integer age;
public User(String name,Integer age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<!--Bean的构造方法的属性注入=============================-->
<bean id="user" class="com.linmin.ioc.demo4.User">
<constructor-arg name="name" value="张三" />
<constructor-arg name="age" value="23"/>
</bean>
/*SpringDemo4.java*/
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean("user");
System.out.println(user);
}
public class Cat {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
public class Person {
private String name;
private Integer age;
private Cat cat;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", cat=" + cat +
'}';
}
}
<!--Bean的set方法的属性注入==============================-->
<bean id="person" class="com.linmin.ioc.demo4.Person">
<property name="name" value="李四"/>
<property name="age" value="32"/>
<property name="cat" ref="cat"/>
</bean>
<bean id="cat" class="com.linmin.ioc.demo4.Cat">
<property name="name" value="ketty"/>
</bean>
使用set方法注入,在Spring配置文件中,通过< property >设置注入属性
第一种,value注入属性为普通类型的,如String,int型:
< property name="" value="">
第二种,ref注入属性为对象的,值为该bean的id或name
< property name="" ref=""/>
/*SpringDemo4.java*/
@Test
public void demo2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person)applicationContext.getBean("person");
System.out.println(person);
}
<!--Bean的p名称空间的属性注入==============================-->
<bean id="person" class="com.linmin.ioc.demo4.Person" p:name="大黄" p:age="34" p:cat-ref="cat"/>
<bean id="cat" class="com.linmin.ioc.demo4.Cat" p:name="小黄"/>
/*SpringDemo4.java*/
@Test
public void demo2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person)applicationContext.getBean("person");
System.out.println(person);
}
public class Category {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Category{" +
"name='" + name + '\'' +
'}';
}
}
public class Product {
private String name;
private Double price;
private Category category;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", price=" + price +
", category=" + category +
'}';
}
}
public class ProductInfo {
public Double calculatePrice(){
return Math.random() * 199;
}
}
<!--Bean的SpEL的属性注入==============================-->
<bean id="category" class="com.linmin.ioc.demo4.Category">
<property name="name" value="#{'服装'}"/>
</bean>
<bean id="productInfo" class="com.linmin.ioc.demo4.ProductInfo"/>
<bean id="product" class="com.linmin.ioc.demo4.Product">
<property name="name" value="#{'男装'}"/>
<property name="price" value="#{productInfo.calculatePrice()}"/>
<property name="category" value="#{category}"/>
</bean>
/*SpringDemo4.java*/
@Test
public void demo3(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Product product = (Product)applicationContext.getBean("product");
System.out.println(product);
}
public class CollectionBean {
private String[] arrs; // 数组类型
private List<String> list;// List集合类型
private Set<String> set; // Set集合类型
private Map<String,Integer> map;// Map集合类型
private Properties properties; // 属性类型
public String[] getArrs() {
return arrs;
}
public void setArrs(String[] arrs) {
this.arrs = arrs;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Map<String, Integer> getMap() {
return map;
}
public void setMap(Map<String, Integer> map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollectionBean{" +
"arrs=" + Arrays.toString(arrs) +
", list=" + list +
", set=" + set +
", map=" + map +
", properties=" + properties +
'}';
}
}
<!--集合类型的属性注入=================================-->
<bean id="collectionBean" class="com.linmin.ioc.demo5.CollectionBean">
<!--数组类型-->
<property name="arrs">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<!--List集合的属性注入-->
<property name="list">
<list>
<!--如果是对象注入要用到ref-->
<value>111</value>
<value>222</value>
<value>333</value>
</list>
</property>
<!--Set集合的属性注入-->
<property name="set">
<set>
<value>ddd</value>
<value>eee</value>
<value>fff</value>
</set>
</property>
<!--Map集合的属性注入-->
<property name="map">
<map>
<entry key="aaa" value="111"/>
<entry key="bbb" value="222"/>
<entry key="ccc" value="333"/>
</map>
</property>
<!--Properties的属性注入-->
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>
/*SpringDemo5.java*/
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CollectionBean collectionBean = (CollectionBean)applicationContext.getBean("collectionBean");
System.out.println(collectionBean);
}
@Repository("userDao")
public class UserDao {
public void save(){
System.out.println("DAO中保存用户...");
}
}
/**
* Spring的Bean管理的注解方式:
* * 传统方式需要去XML中配置
*/
//@Component("userService")
@Service("userService")
public class UserService {
@Value("米饭")
private String something;
/*@Autowired
@Qualifier("userDao")*/
@Resource(name="userDao")
private UserDao userDao;
public String sayHello(String name){
return "Hello" + name;
}
public void eat(){
System.out.println("eat:"+something);
}
public void save(){
System.out.println("Service中保存用户...");
userDao.save();
}
}
public class SpringDemo1 {
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
String s = userService.sayHello("张三");
System.out.println(s);
}
@Test
public void demo2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.eat();
}
@Test
public void demo3(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.save();
}
@Component("bean1")
public class Bean1 {
@PostConstruct
public void init(){
System.out.println("initBean...");
}
public void say(){
System.out.println("say...");
}
@PreDestroy
public void destory(){
System.out.println("destoryBean...");
}
}
@Component("bean2")
@Scope("prototype")
public class Bean2 {
}
public class SpringDemo2 {
@Test
public void demo1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Bean1 bean1 = (Bean1)applicationContext.getBean("bean1");
bean1.say();
applicationContext.close();
}
@Test
public void demo2(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Bean2 bean1 = (Bean2)applicationContext.getBean("bean2");
Bean2 bean2 = (Bean2)applicationContext.getBean("bean2");
System.out.println(bean1 == bean2);//结果为true,单例模式
}
}