Spring之bean对象

2023-05-16

目录

一、了解Bean

二、Bean的生命周期

三、Bean的应用

单例模式

多例模式

单例模式与多例模式优劣势:


一、了解javaBean

 什么是javaBean对象?

在Spring 中,构成应用程序主干并由Spring ioc容器管理的对象称为bean。bean是一个由Spring ioc容器实例化、组装和管理的对象。

我们总结如下:
1.bean是对象,一个或者多个不限定
2.bean由Spring中一个叫ioC的东西管理

二、Bean的生命周期

Spring Bean的生命周期:
1)通过XML、Java annotation(注解)以及Java Configuration(配置类)
等方式加载Spring Bean

2)BeanDefinitionReader:解析Bean的定义。在Spring容器启动过程中,
会将Bean解析成Spring内部的BeanDefinition结构;
理解为:将spring.xml中的<bean>标签转换成BeanDefinition结构
有点类似于XML解析

3)BeanDefinition:包含了很多属性和方法。例如:id、class(类名)、
scope、ref(依赖的bean)等等。其实就是将bean(例如<bean>)的定义信息
存储到这个对应BeanDefinition相应的属性中

例如:
<bean id="" class="" scope=""> -----> BeanDefinition(id/class/scope)

4)BeanFactoryPostProcessor:是Spring容器功能的扩展接口。

注意:
1)BeanFactoryPostProcessor在spring容器加载完BeanDefinition之后,
在bean实例化之前执行的
2)对bean元数据(BeanDefinition)进行加工处理,也就是BeanDefinition
属性填充、修改等操作

5)BeanFactory:bean工厂。它按照我们的要求生产我们需要的各种各样的bean。


6)Aware感知接口:在实际开发中,经常需要用到Spring容器本身的功能资源
例如:BeanNameAware、ApplicationContextAware等等
BeanDefinition 实现了 BeanNameAware、ApplicationContextAware

7)BeanPostProcessor:后置处理器。在Bean对象实例化和引入注入完毕后,
在显示调用初始化方法的前后添加自定义的逻辑。(类似于AOP的绕环通知)

前提条件:如果检测到Bean对象实现了BeanPostProcessor后置处理器才会执行
Before和After方法
BeanPostProcessor
1)Before
2)调用初始化Bean(InitializingBean和init-method,Bean的初始化才算完成)
3)After

完成了Bean的创建工作

8)destory:销毁
 

如图


三、Bean的应用

测试代码

package beanLife;

public class Demo1 {
    
        public static void main(String[] args) {
            Person p=new Person();
         
            p.setSex("女");//实例化后修改属性
       System.out.println(p.getSex());
          
        }
    
    

}
 class Person{
     private String name;
     private int age;
     private String sex;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
     
    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }
//    
     public Person() {
         this.init();
         this.name="小三";
         this.age=23;
         this.sex="未知";
         
     }
     public void init() {
         
     }
     
 }
 

图片1

改进后

package beanLife;

public class Demo1 {
    
        public static void main(String[] args) {
//            Person p=new Person();
//            Person p1=new Person();
//            Person p2=new Person();
//            Person p3=new Person();
            Person p0=Person.newInstance();
            Person p1=Person.newInstance();
            Person p2=Person.newInstance();
            Person p3=Person.newInstance();
//            p.setSex("女");//实例化后修改属性
            System.out.println(p0);
            System.out.println(p1);
            System.out.println(p2);
            System.out.println(p3);

        }
    
    

}
 class Person{
    
     private Person() {
         
     }
     private final static Person p=new Person();
     
     public static Person newInstance() {
         return p;
     }
     
//     public void init() {
//         
//     }
     
 }
 

图片2

单例模式

 单例模式的使用原因:

举个例子1

一个类如果被使用了100次,如果这个项目一共有1万个类,那么Spring上下文要创建多少个对象?

答案:一共需要一百万个对象

 如下面代码

package beanLife;

public class Demo1 {
    
        public static void main(String[] args) {
//            Person p=new Person();
//            Person p1=new Person();
//            Person p2=new Person();
//            Person p3=new Person();
            Person p0=Person.newInstance();
            Person p1=Person.newInstance();
            Person p2=Person.newInstance();
            Person p3=Person.newInstance();
//            p.setSex("女");//实例化后修改属性
            System.out.println(p0);
            System.out.println(p1);
            System.out.println(p2);
            System.out.println(p3);

        }   

}
 class Person{
    
     private Person() {
         
     }
     private final static Person p=new Person();
     
     public static Person newInstance() {
         return p;
     }

 }
 

 图片--对象

多例模式

举个例子2

一个类在100个地方使用,使得有的都是同一个对象,这个项目有1w个类,请问Spring上下文要创建多少个对象?

答案:1w个对象

单例模式与多例模式优劣势:

 以生活为例

孩子A孩子B 

给两个孩子买同一个玩具各自买不同的玩具,其中的优缺点为;

买一种玩具,买两份(多例模式):

缺点:种类单一,成本大;优点:数量多,孩子容易满足,减少不必要的争夺

买不同的玩具,各买一份(单例模式)

 缺点:玩具被前者使用过,容易造成污染,孩子容易产生不公平心理,优点:玩具种类多

代码:

package beanLife;

import java.util.List;


import com.zking.biz.UserBiz;
import impl.UserBizImpl1;
import impl.UserBizImpl2;

/**验证单例模式与多例模式的区别
 * @author lucy
 *
 */
public class ParamAction {
	private int age;
	private String name;
	private List<String> hobby;
	private int num = 1;//变量
	// private UserBiz userBiz = new UserBizImpl1();

	public ParamAction() {
		super();
	}

	public ParamAction(int age, String name, List<String> hobby) {
		super();
		this.age = age;
		this.name = name;
		this.hobby = hobby;
	}

	public void execute() {
		// userBiz.upload();
		// userBiz = new UserBizImpl2();
		System.out.println("this.num=" + this.num++);
		System.out.println(this.name);
		System.out.println(this.age);
		System.out.println(this.hobby);
	}
}

package beanLife;

/**
 * @author lucy
 *
 */
public class InstanceFactory {
	public void init() {
		System.out.println("初始化方法");
	}

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

	public void service() {
		System.out.println("业务方法");
	}
}

测试

package beanLife;

import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

/*
 * spring    bean的生命週期
 * spring    bean的單例多例
 */
public class Demo2 {
    // 体现单例与多例的区别
    @Test
    public void test1() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
        ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");
        ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
        // System.out.println(p1==p2);
        p1.execute();
        p2.execute();
        
//        单例时,容器销毁instanceFactory对象也销毁;多例时,容器销毁对象不一定销毁;
        applicationContext.close();
    }

    // 体现单例与多例的初始化的时间点 instanceFactory
    @Test
    public void test2() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
    }

    // BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式
    // 默认情况下bean的初始化,单例模式立马会执行,但是此时XmlBeanFactory作为子类,单例模式下容器创建,bean依赖没有初始化,只有要获取使用bean对象才进行初始化
    @Test
    public void test3() {
        // ClassPathXmlApplicationContext applicationContext = new
        // ClassPathXmlApplicationContext("/spring-context.xml");

        Resource resource = new ClassPathResource("/spring-context.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
//        InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");
        
    }

}
 

多例举例

<?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:aop="http://www.springframework.org/schema/aop"
    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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        
    <!-- ioc的作用是管理整个项目,依靠依赖注入,控制反转的特点进行管理javabean对象  -->
    <bean class="impl.UserBizImpl1" id="userBiz" scope="prototype" ></bean> 
    <!-- 1. set注入-->
    <bean class="com.zking.web.UserAction" id="userAction">
     <property name="userbiz" ref="userBiz"></property>
    <property name="age" value="23"></property>
    <property name="name" value="占星师"></property>
    <property name="hobby" >
    <list>
    <value>rap</value>
    <value>画画</value>
    <value>看沉香</value>
    </list>
    
    </property>
    </bean>
    <!-- 1. 构造方法注入-->
    <bean class="com.zking.web.OrderAction" id="orderAction">
   <property name="userbiz" ref="userBiz"></property> 
    <constructor-arg name="age" value="14"></constructor-arg>
    <constructor-arg name="name" value="小小"></constructor-arg>
    <constructor-arg name="hobby" >
    <list>
    <value>rap</value>
    <value>画画</value>
    <value>看沉香</value>
    </list>
    </constructor-arg>
    </bean>
    <!-- 目标对象 -->
    <bean class="impl.BookBizImpl" id="bookBiz"></bean>
    <!-- 前置通知 -->
    <bean class="com.zking.aop.advice.MyMethodBeforeAdvice" id="myBefore"></bean>
    <!-- 后置通知 -->
    <bean class="com.zking.aop.advice.MyAfterReturningAdvice" id="myAfter"></bean>
    <!-- 环绕通知 -->
    <bean class="com.zking.aop.advice.MyMethodInterceptor" id="myMethod"></bean>
    
    <!-- 异常通知 -->
    <bean class="com.zking.aop.advice.MyThrowAdvice" id="myThrow"></bean>
    <!-- 过滤通知 给后置通知添加过滤通知 只有买书返利,评论不返利 -->
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="myafterPlus">
    <property name="advice" ref="myAfter"></property>
    <property name="pattern" value=".*buy"></property>
    </bean>
    
    
    <!-- 代理对象=目标+通知 -->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
    <!--目标  -->
    <property name="target" ref="bookBiz"></property>
    <!--通知  实现的接口列表-->
    <property name="proxyInterfaces">
    <list>
        <value>com.zking.aop.biz.BookBiz</value>
    </list>
    </property>
    <!-- 通知 调用目标方法时,会调用下面指定的通知  -->
    <property name="interceptorNames">
    <list>
        <value>myBefore</value>
         <value>myAfter</value>
        <!-- <value>myafterPlus</value> -->
        <value>myMethod</value>
        <value>myThrow</value>
    </list>
    </property>
    <!--辅助理论理解的配置  -->
    </bean>
    <bean id="paramAction" class="beanLife.ParamAction">
        <constructor-arg name="name" value="三丰"></constructor-arg>
        <constructor-arg name="age" value="21"></constructor-arg>
        <constructor-arg name="hobby">
            <list>
                <value>抽烟</value>
                <value>烫头</value>
                <value>大保健</value>
            </list>
        </constructor-arg>
    </bean>

    <bean id="instanceFactory" class="beanLife.InstanceFactory"
        scope="prototype" init-method="init" destroy-method="destroy"></bean>
            
    
    
</beans>
 

 

 单例举例

<?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:aop="http://www.springframework.org/schema/aop"
    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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        
    <!-- ioc的作用是管理整个项目,依靠依赖注入,控制反转的特点进行管理javabean对象  -->
    <bean class="impl.UserBizImpl1" id="userBiz"scope="singleton"></bean>
    <!-- 1. set注入-->
    <bean class="com.zking.web.UserAction" id="userAction">
     <property name="userbiz" ref="userBiz"></property>
    <property name="age" value="23"></property>
    <property name="name" value="占星师"></property>
    <property name="hobby" >
    <list>
    <value>rap</value>
    <value>画画</value>
    <value>看沉香</value>
    </list>
    
    </property>
    </bean>
    <!-- 1. 构造方法注入-->
    <bean class="com.zking.web.OrderAction" id="orderAction">
   <property name="userbiz" ref="userBiz"></property> 
    <constructor-arg name="age" value="14"></constructor-arg>
    <constructor-arg name="name" value="小小"></constructor-arg>
    <constructor-arg name="hobby" >
    <list>
    <value>rap</value>
    <value>画画</value>
    <value>看沉香</value>
    </list>
    </constructor-arg>
    </bean>
    <!-- 目标对象 -->
    <bean class="impl.BookBizImpl" id="bookBiz"></bean>
    <!-- 前置通知 -->
    <bean class="com.zking.aop.advice.MyMethodBeforeAdvice" id="myBefore"></bean>
    <!-- 后置通知 -->
    <bean class="com.zking.aop.advice.MyAfterReturningAdvice" id="myAfter"></bean>
    <!-- 环绕通知 -->
    <bean class="com.zking.aop.advice.MyMethodInterceptor" id="myMethod"></bean>
    
    <!-- 异常通知 -->
    <bean class="com.zking.aop.advice.MyThrowAdvice" id="myThrow"></bean>
    <!-- 过滤通知 给后置通知添加过滤通知 只有买书返利,评论不返利 -->
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="myafterPlus">
    <property name="advice" ref="myAfter"></property>
    <property name="pattern" value=".*buy"></property>
    </bean>
    
    
    <!-- 代理对象=目标+通知 -->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
    <!--目标  -->
    <property name="target" ref="bookBiz"></property>
    <!--通知  实现的接口列表-->
    <property name="proxyInterfaces">
    <list>
        <value>com.zking.aop.biz.BookBiz</value>
    </list>
    </property>
    <!-- 通知 调用目标方法时,会调用下面指定的通知  -->
    <property name="interceptorNames">
    <list>
        <value>myBefore</value>
         <value>myAfter</value>
        <!-- <value>myafterPlus</value> -->
        <value>myMethod</value>
        <value>myThrow</value>
    </list>
    </property>
    <!--辅助理论理解的配置  -->
    </bean>
    <bean id="paramAction" class="beanLife.ParamAction">
        <constructor-arg name="name" value="三丰"></constructor-arg>
        <constructor-arg name="age" value="21"></constructor-arg>
        <constructor-arg name="hobby">
            <list>
                <value>抽烟</value>
                <value>烫头</value>
                <value>大保健</value>
            </list>
        </constructor-arg>
    </bean>

    <bean id="instanceFactory" class="beanLife.InstanceFactory"
        scope="prototype" init-method="init" destroy-method="destroy"></bean>
            
    
    
</beans>
 

总结:】

两者区别、特点:

单例模式下javabean的生命周期:

“容器对象生,容器对象死”

 多例模式下javabean的生命周期;

“使用时对象生,死亡跟着jvm垃圾回收机制走”

特点:bean的初始化时间点,除了与bena管理模式(单例、多例) 有关,还跟BeanFactory的子类有关


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring之bean对象 的相关文章

随机推荐