Spring—bean

一、bean的作用域

单例

默认化为:单例(singleton)

SpringBean类:

java 复制代码
package com.hei.bean;
public class SpringBean {
public SpringBean(){
    System.out.println("Springbean的无参数构造方法执行了");
}
}

spring,xml:

XML 复制代码
<bean id="sb" class="com.hei.bean.SpringBean"></bean>

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void Test() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        SpringBean s1= applicationContext.getBean("sb", SpringBean.class);
        System.out.println(s1);
        SpringBean s2= applicationContext.getBean("sb", SpringBean.class);
        System.out.println(s2);
        SpringBean s3= applicationContext.getBean("sb", SpringBean.class);
        System.out.println(s3);
        }
    }

多例

可以手动的调用多例对象(prototype),在xml中利用 scope:

spring.xml:

XML 复制代码
<bean id="sb" class="com.hei.bean.SpringBean" scope="prototype"></bean>

scope

工厂模式的三种形态

简单工厂模式

抽象产品类:

java 复制代码
package test1;
 public abstract class Weapon {//抽象类
    public abstract void attack();
}

具体产品类:

java 复制代码
package test1;
public class Tank extends Weapon{//具体类
    @Override
    public void attack(){
        System.out.println("坦克准备起步...");
    }
}

package test1;
public class Figter extends Weapon{//具体类
    @Override
    public void attack(){
        System.out.println("战斗机准备起飞...");
    }
}

package test1;
public class Dagg extends Weapon{//具体类
    @Override
    public void attack(){
        System.out.println("某某某正在砍敌人");
    }
}

工厂类:

java 复制代码
package test1;
public class WeaponFactory {//工厂类
    //静态方法:要获取什么产品,就看你传的什么参数
    //简单工厂模式中有一个静态方法,被称为静态工厂方法模式
    public static Weapon Get(String type){
        if("Tank".equals(type)){
            return new Tank();
        }else if("Figter".equals(type)){
            return new Figter();
        }else if("Dagg".equals(type)){
            return new Dagg();
        }
        return null;
    }
}

测试类:

java 复制代码
public class test1 {
    public static void main(String[] args)  {
       Weapon t= WeaponFactory.Get("Tank");
       t.attack();
        Weapon f= WeaponFactory.Get("Figter");
        f.attack();
        Weapon d= WeaponFactory.Get("Dagg");
        d.attack();

    }
    }

工厂方法模式

抽象产品:

java 复制代码
package test1;
 public abstract class Weapon {//抽象类
    public abstract void attack();
}

具体产品:

java 复制代码
package test1;
public class Tank extends Weapon{//具体类
    @Override
    public void attack(){
        System.out.println("坦克准备起步...");
    }
}

package test1;
public class Dagg extends Weapon{//具体类
    @Override
    public void attack(){
        System.out.println("某某某正在砍敌人");
    }
}

抽象工厂:

java 复制代码
package test1;
public abstract class WeaponFactory {//抽象工厂
    public abstract Weapon Get();
}

具体工厂:

java 复制代码
package test1;
public class TankFactory extends WeaponFactory{
    @Override
    public Weapon Get() {
        return new Tank();
    }
}

package test1;
public class DaggFactory extends WeaponFactory{
    @Override
    public Weapon Get() {
        return new Dagg();
    }
}

测试类:

java 复制代码
public class test1 {
    public static void main(String[] args)  {
        WeaponFactory weaponFactory=new TankFactory();
        Weapon tank=weaponFactory.Get();
        tank.attack();
        WeaponFactory weaponFactory1=new DaggFactory();
        Weapon dagg=weaponFactory1.Get();
        dagg.attack();

    }
    }

Bean的实例化方法

1.通过构造方法实例化

在配置文件(spring.xml)中,进行bean的实例化。

SpringBean类:

java 复制代码
package com.hei.bean;
public class SpringBean {
public SpringBean(){
    System.out.println("Springbean的无参数构造方法执行了");
}
}

spring.xml:

XML 复制代码
<bean id="sb" class="com.hei.bean.SpringBean"></bean>

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void Test() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        SpringBean s1= applicationContext.getBean("sb", SpringBean.class);
        System.out.println(s1);
        }
    }

2.通过简单工厂模式实例化

产品类:

java 复制代码
package com.hei.bean;
public class Star {
    public Star(){
        System.out.println("Star的无参构造方法");
    }
}

工厂类:

java 复制代码
package com.hei.bean;
public class StarFacroty {
    public static Star get(){
        return new Star();
    }
}

spring.xml中:

XML 复制代码
<!--   在Spring配置文件中告诉Spring框架,调用哪个类哪个方法创建bean-->
    <bean id="star" class="com.hei.bean.StarFacroty" factory-method="get"></bean>

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void Test() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        Star s= applicationContext.getBean("star", Star.class);
        System.out.println(s);
        }
    }

3.通过factory-bean实例化(工厂方法模式)

具体产品类:

java 复制代码
package com.hei.bean;
public class Gun {//具体产品
    public Gun(){
        System.out.println("Gun的无参数构造方法");
    }
}

具体工厂类:

java 复制代码
package com.hei.bean;
public class GunFactory {//具体工厂
    public Gun get(){
        return new Gun();
    }
}

spring.xml:

XML 复制代码
<!--通过工厂方法模型,结合factory-bean+factory-method-->
    <bean id="gunfactory" class="com.hei.bean.GunFactory"></bean>
<!-- factory-bean告诉Spring调用哪个对象,factory-method告诉Spring调用该对象的哪个方法-->
   <bean id="gun" factory-bean="gunfactory" factory-method="get"></bean>

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void Test() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        Gun g = applicationContext.getBean("gun", Gun.class);
        System.out.println(g);
        }
    }

4.通过FactoryBean接口实例化

对第三种方式的一种简化:

Person类:

java 复制代码
package com.hei.bean;
public class Person {
    public Person(){
        System.out.println("Person的无参构造");
    }
}

PersonFactoryBean类:

java 复制代码
package com.hei.bean;
import org.springframework.beans.factory.FactoryBean;
public class PersonFactoryBean implements FactoryBean<Person> {
    @Override
    //最主要的方法
    public Person getObject() throws Exception {
        return new Person();
    }
    @Override
    public Class<?> getObjectType() {
        return null;
    }
    //判断是不是为单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}

spring.xml:

XML 复制代码
<!--是第三种方式的简化-->
    <bean id="person" class="com.hei.bean.PersonFactoryBean"></bean>

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void Test() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        Person p = applicationContext.getBean("person", Person.class);
        System.out.println(p);
        }
    }

BeanFactory和FactoryBean区别

FactoryBean实际应用注入Date

student类:

定义一个Date类型的日期,通过set方法赋值。

java 复制代码
package com.hei.bean;
import java.util.Date;
public class Student {
    private Date brith;
    public void setBrith(Date brith) {
        this.brith = brith;
    }
    @Override
    public String toString() {
        return "Student{" +
                "brith=" + brith +
                '}';
    }
}

StudentFactoryBean类:

要设置一个日期,需要在程序中传一个字符串(代表日期)

java 复制代码
package com.hei.bean;
import org.springframework.beans.factory.FactoryBean;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StudentFactoryBean implements FactoryBean<Date> {
    private String strdate;
    public StudentFactoryBean(String strdate) {
        this.strdate = strdate;
    }
    @Override
    public Date getObject() throws Exception {
        //创建日期
        SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd");
        Date date=s.parse(strdate);
        return date;
    }
    @Override
    public Class<?> getObjectType() {
        return null;
    }
    @Override
    public boolean isSingleton() {
        return true;
    }
}

spring.xml:

XML 复制代码
<bean id="date" class="com.hei.bean.StudentFactoryBean">
    <constructor-arg index="0" value="2003-12-15"></constructor-arg>
</bean>
    <bean id="student" class="com.hei.bean.Student">
        <property name="brith" ref="date"></property>
    </bean>

测试类:

java 复制代码
package com.hei;
import com.hei.bean.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
    @org.junit.Test
    public void Test() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        Student s = applicationContext.getBean("student",Student.class);
        System.out.println(s);
        }
    }

Bean的生命周期

Bean的生命周期之五步

第一步:实例化Bean是调用此方法的无参构造。

第二步:Bean属性赋值,调用Set方法进行。

第三步:初始化Bean,在类中自己定义一个初始化方法。

第四步:使用Bean,要在spring.xml配置文件中,手动指定初始化方法名和销毁方法名,还需给属性赋值。

第五步:销毁Bean, 在类中自己定义一个销毁方法。

注:在测试类中,要想销毁Bean需关闭spring容器,applicationContext是一个抽象类,需要转换类型为ClassPathXmlApplicationContext.

User类:

java 复制代码
package com.hei.bean;
public class User {
    private String name;
    public User() {
       System.out.println("第一步 无参数构造方法执行");
    }
    public void setName(String name) {
        System.out.println("第二步 给bean属性赋值");
        this.name = name;
    }
    public void InitaBean(){
        System.out.println("第三步 初始化bean");
    }
    public void destoryBean(){
        System.out.println("第五步 销毁bean");
    }
}

spring.xml:

XML 复制代码
<!--需要手动指定初始化方法和销毁方法-->
    <bean id="Bean" class="com.hei.bean.User" init-method="InitaBean" destroy-method="destoryBean">
        <property name="name" value="zhangsan"></property>
</bean>

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void Test() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        User user= applicationContext.getBean("Bean",User.class);
        System.out.println("第四步 使用bean "+user);
        //使用完了之后要销毁bean,需关闭Spring容器
        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
        context.close();
    }
    }

Bean的生命周期之七步

User类:

java 复制代码
package com.hei.bean;
public class User {
    private String name;
    public User() {
       System.out.println("第一步 无参数构造方法执行");
    }
    public void setName(String name) {
        System.out.println("第二步 给bean属性赋值");
        this.name = name;
    }
    public void InitaBean(){
        System.out.println("第三步 初始化bean");
    }
    public void destoryBean(){
        System.out.println("第五步 销毁bean");
    }
}

Bean后处理器:BeanPost类:

java 复制代码
package com.hei.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class Beanpost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       System.out.println("执行Bean后处理器的before方法");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行Bean后处理器的after方法");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

spring.xml:

XML 复制代码
<!--配置Bean后处理器-->
<!-- Bean后处理器将作用于当前配置文件所有的bean-->
    <bean class="com.hei.bean.Beanpost"></bean>
    <!--需要手动指定初始化方法和销毁方法-->
    <bean id="Bean" class="com.hei.bean.User" init-method="InitaBean" destroy-method="destoryBean">
        <property name="name" value="zhangsan"></property>
</bean>

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void Test() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        User user= applicationContext.getBean("Bean",User.class);
        System.out.println("第四步 使用bean "+user);
        //使用完了之后要销毁bean,需关闭Spring容器
        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
        context.close();
    }
    }

Bean的生命周期之十步

User类:

java 复制代码
package com.hei.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
    private String name;
    public User() {
       System.out.println("第一步 无参数构造方法执行");
    }
    public void setName(String name) {
        System.out.println("第二步 给bean属性赋值");
        this.name = name;
    }
    public void InitaBean(){
        System.out.println("第四步 初始化bean");
    }
    public void destoryBean(){
        System.out.println("第七步 销毁bean");
    }
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("Bean这个类的加载器:"+classLoader);
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("生产这个Bean的工厂:"+beanFactory);
    }
    @Override
    public void setBeanName(String s) {
        System.out.println("这个Bean的名字:"+s);
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean's destory的方法执行");

    }
    @Override
    public void afterPropertiesSet() throws Exception {
         System.out.println("InitializingBean's afterPropertiesSet的方法执行");
    }
}

只需在User类中添加多个接口,其他类和配置文件不变。

Bean生命周期不同作用域

spring容器只对singleton(单例)的Bean进行完整的生命周期管理。

如果是prototype(多例)作用域的Bean,Spring容器只负责将该Bean初始化完毕,等客户端程序一旦获取到该Bean之后,到使用Bean之后,Spring容器就不再管理该对象的生命周期了。

自己new的对象纳入Spring容器管理

Student类:

java 复制代码
package com.hei.bean;
public class Student {
}

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void test() {
        Student s = new Student();
        System.out.println(s);
        //将new的对象交给spring容器管理
        DefaultListableBeanFactory d = new DefaultListableBeanFactory();
        d.registerSingleton("student", s);
        //从spring容器中获取
        Object S= d.getBean("student");
        System.out.println(S);
    }
}

Bean的循环依赖

循环依赖:

单例和set模式下的循环依赖

husband类:

java 复制代码
package com.hei.bean;
public class Husband {
    private String name;
    private Wife wife;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
    @Override
    public String toString() {
        return "Husband{" +
                "name='" + name + '\'' +
                ", wife=" + wife.getName() +
                '}';
    }
}

wife类:

java 复制代码
package com.hei.bean;
public class Wife {
    private String name;
    private Husband husband;
    public void setName(String name) {
        this.name = name;
    }
    public void setHusband(Husband husband) {
        this.husband = husband;
    }
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return "Wife{" +
                "name='" + name + '\'' +
                ", husband=" + husband.getName() +
                '}';
    }
}

spring.xml:

XML 复制代码
<bean id="hus" class="com.hei.bean.Husband" scope="singleton">
    <property name="name" value="张三"/>
    <property name="wife" ref="wife"></property>
</bean>
    <bean id="wife" class="com.hei.bean.Wife" scope="singleton">
        <property name="name" value="小花"/>
        <property name="husband" ref="hus"></property>
    </bean>

测试类:

java 复制代码
public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        Wife w= applicationContext.getBean("wife",Wife.class);
        System.out.println(w);
        Husband h= applicationContext.getBean("hus",Husband.class);
        System.out.println(h);
    }
    }

多例和set模式下的循环依赖

当两个bean的scope都是prototype(多例)会出现异常,若其中一个为singleton(单例)就不会出现异常。

相关推荐
suweijie7683 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿4 小时前
List深拷贝后,数据还是被串改
java
向前看-7 小时前
验证码机制
前端·后端
xlsw_7 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹8 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭8 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫8 小时前
泛型(2)
java
超爱吃士力架9 小时前
邀请逻辑
java·linux·后端
南宫生9 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石9 小时前
12/21java基础
java