Spring面试重点(一)——Spring容器

news2025/6/9 15:21:49

Spring容器

手写Autowired注解

/** 实现spring的Autowired注解 **/
//运行时触发
@Retention(RetentionPolicy.RUNTIME)
//作用于变量
@Target(ElementType.FIELD)
public @interface Autowired {

}
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 不注入
     * 私有属性,编译器就放到访问标志符
     */
    private Integer integer;

    private String name;

    public UserService getUserService() {
        return userService;
    }

    //get,set...
}

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.stream.Stream;

/**
 * Title:反射实现ioc
 * Description:
 *
 * spring可扩展:
 * 容器初始化前扩展
 * 对象创建前扩展
 * 不同阶段监听事件
 * 面向接口编程
 *
 * @author WZQ
 * @version 1.0.0
 * @date 2021/1/27
 */
public class Test {

    public static void main(String[] args) throws Exception{
        //反射测试
        UserController userController = new UserController();
        UserService userService = new UserService();
        Class<? extends UserController> clazz = userController.getClass();
        //Declared可以拿到private、default、protected、public
        //但是只能是自己类的,父类的属性拿不到
        //解决方法:
        //一、getFields(),通过set,get方法访问
        //二、getDeclaredFields(),递归父类
        Field[] declaredFields = clazz.getDeclaredFields();
        //拿到所有public
        Field[] fields = clazz.getFields();

        Field f = clazz.getDeclaredField("userService");
        //私有访问,开启暴力
        f.setAccessible(true);
        f.set(userController, userService);
        System.out.println(userController.getUserService());

        //通过set方法注入
        String fieldName = f.getName();
        fieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        String methodName = "set" + fieldName;
        Method method = clazz.getMethod(methodName, UserService.class);
        method.invoke(userController, userService);
        System.out.println(userController.getUserService());



        //spring容器的核心原理
        //通过类模板获取controller的所有属性,遍历属性是否有Autowired注解
        Stream.of(clazz.getDeclaredFields()).forEach(field -> {
            String name = field.getName();
            //拿到属性的注解,不为空则set依赖对象
            Autowired annotation = field.getAnnotation(Autowired.class);
            if (annotation != null){
                field.setAccessible(true);
                Class<?> type = field.getType();
                try {
                    //spring通过beanName从容器拿到对象,注入属性
                    /**
                     spring容器流程,扩展性
                     底层结构:
                     Map<beanName, BeanDefinition> map
                     Map<class, BeanDefinition> map

                     BeanDefinitionReader读取 xml | annotation获取bean信息
                     BeanDefinitionRegister
                     实例化BeanDefinition信息到容器
                     可通过BeanFactoryPostProcessor增强扩展工厂

                     工厂BeanFactory:Object o = type.getConstructor().newInstance();
                     通过BeanDefinition实例化对象到容器
                     可通过BeanPostProcessor增强扩展Bean

                     实例化对象前processor扩展
                     初始化对象前processor扩展
                     初始化对象后processor扩展

                     Environment环境
                     */
                    
                    //也可以通过set方法注入
                    Object o = type.getConstructor().newInstance();
                    field.set(userController, o);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
        });
    }

}

Profile注解

//在dev环境下才注入
@Profile("dev")
@Configuration
public class DevConfiguration{
   
}

//根据不同环境读取相应的配置
java -jar -Dspring.profiles.active=test -Dserver.port=8080 xxx.class

核心接口

父子容器的关系:

从子容器中拿Bean,拿不到再从父容器里拿。子容器的Bean可以覆盖父容器的Bean。

  • BeanFactory,ioc最基础工厂,定义bean工厂的规范,主要方法有getBean(String name)、containsBean(String name)、isSingleton(String name)、isPrototype(String name)、getType(String name)等等。

  • ListableBeanFactory,继承BeanFactory,管理bean信息,也就是管理BeanDefinition,除了基础BeanFactory方法,还有containsBeanDefinition(String beanName)、getBeanDefinitionNames()、getBeanNamesForType(@Nullable Class<?> type)等等。

  • ApplicationContext,允许容器通过应用程序上下文环境创建、获取、管理bean。继承了很多接口,访问应用程序组件的Bean工厂方法,从ListableBeanFactory继承。以通用方式加载文件资源的能力,继承自ResourceLoader接口。向注册侦听器发布事件的能力,继承自ApplicationEventPublisher接口。解析消息的能力,支持国际化,继承自MessageSource接口。从父上下文继承,后代上下文中的定义总是优先级。例如,这意味着单个父上下文可以被整个web应用程序使用,而每个servlet都有自己独立于任何其他servlet的子上下文。

    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    
  • HierarchicalBeanFactory(haɪəˈrɑːkɪkl),获取工厂的父子关系

  • xxxAware,Aware类都是调用setXXX方法获取容器组件信息注入到Bean中

  • Environment,获取环境配置文件properties/yml,解析

@NotNull不为NULL,@Nullable可为NULL。

BeanFactory和FactoryBean的区别

1.BeanFactory

BeanFactory是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范,例如DefaultListableBeanFactory,

XmlBeanFactory,ApplicationContext 等具体的容器都是实现了BeanFactory,再在其基础之上附加了其他的功能。

BeanFactory源码

package org.springframework.beans.factory;  
import org.springframework.beans.BeansException;  
public interface BeanFactory {  
    String FACTORY_BEAN_PREFIX = "&";  
    Object getBean(String name) throws BeansException;  
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;  
    <T> T getBean(Class<T> requiredType) throws BeansException;  
    Object getBean(String name, Object... args) throws BeansException;  
    boolean containsBean(String name);  
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;  
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;  
    boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;  
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;  
    String[] getAliases(String name);  
}

2.FactoryBean

FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&。openFegin用到FactoryBean

为啥要FactoryBean?为啥要getObject()获取Bean?

可以在getObject方法写自己的逻辑,生成自定义的对象,扩展工厂生产对象。

FactoryBean源码

package org.springframework.beans.factory;  
public interface FactoryBean<T> {  
    T getObject() throws Exception;  
    Class<?> getObjectType();  
    boolean isSingleton();  
}

下面是一个应用FactoryBean的例子

<beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xmlns:tx="http://www.springframework.org/schema/tx"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                     http://www.springframework.org/schema/context
                     http://www.springframework.org/schema/context/spring-context-3.0.xsd
                     http://www.springframework.org/schema/aop
                     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                     http://www.springframework.org/schema/tx
                     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    
 <bean id="student" class="com.spring.bean.Student">  
  <property name="name" value="zhangsan" />  
 </bean>  
 
 <bean id="school" class="com.spring.bean.School">  
 </bean> 
 
 <bean id="factoryBeanPojo" class="com.spring.bean.FactoryBeanPojo">  
    <property name="type" value="student" />
 </bean> 
</beans>

FactoryBean的实现类

import org.springframework.beans.factory.FactoryBean;
 
/** 
 * @author  作者 wangbiao
 * @date 创建时间:2016年11月14日 上午11:19:31 
 * @parameter 
 * @return 
 */
public class FactoryBeanPojo implements FactoryBean{
	private String type;
 
	@Override
	public Object getObject() throws Exception {
		if("student".equals(type)){
			return new Student();			
		}else{
			return new School();
		}
	}
 
	@Override
	public Class getObjectType() {
		return School.class;
	}
 
	@Override
	public boolean isSingleton() {
		return true;
	}
 
	public String getType() {
		return type;
	}
 
	public void setType(String type) {
		this.type = type;
	}
	
}

普通的bean

/** 
 * @author  作者 wangbiao
 * @date 创建时间:2016年11月14日 上午11:13:18 
 * @parameter 
 * @return 
 */
public class School {
	private String schoolName;
	private String address;
	private int studentNumber;
	public String getSchoolName() {
		return schoolName;
	}
	public void setSchoolName(String schoolName) {
		this.schoolName = schoolName;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public int getStudentNumber() {
		return studentNumber;
	}
	public void setStudentNumber(int studentNumber) {
		this.studentNumber = studentNumber;
	}
	@Override
	public String toString() {
		return "School [schoolName=" + schoolName + ", address=" + address
				+ ", studentNumber=" + studentNumber + "]";
	}
}

测试类

import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.spring.bean.FactoryBeanPojo;
 
/** 
 * @author  作者 wangbiao
 * @date 创建时间:2016年11月14日 上午11:11:35 
 * @parameter 
 * @return 
 */
public class FactoryBeanTest {
	public static void main(String[] args){
		String url = "com/spring/config/BeanConfig.xml";
		ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext(url);
		Object school=  cpxa.getBean("factoryBeanPojo");
		FactoryBeanPojo factoryBeanPojo= (FactoryBeanPojo) cpxa.getBean("&factoryBeanPojo");
		System.out.println(school.getClass().getName());
		System.out.println(factoryBeanPojo.getClass().getName());
	}
}

输出的结果:

十一月 16, 2016 10:28:24 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1e8ee5c0: startup date [Wed Nov 16 10:28:24 CST 2016]; root of context hierarchy
十一月 16, 2016 10:28:24 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [com/spring/config/BeanConfig.xml]
十一月 16, 2016 10:28:24 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@35b793ee: defining beans [student,school,factoryBeanPojo]; root of factory hierarchy
com.spring.bean.Student
com.spring.bean.FactoryBeanPojo

BeanFactory和FactoryBean的区别:

BeanFactory和FactoryBean其实没有什么比较性的,只是两者的名称特别接近,所以有时候会拿出来比较一番,BeanFactory是提供了IOC容器最基本的形式,给具体的IOC容器的实现提供了规范,FactoryBean可以说为IOC容器中Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,我们可以在getObject()方法中灵活配置。其实在Spring源码中有很多FactoryBean的实现类,要想深入准确的理解FactoryBean,只有去读读Spring源码了。

*Aware含义

Spring中有很多继承于aware中的接口,这些接口到底是做什么用到的。

在这里插入图片描述

aware,翻译过来是知道的,已感知的,意识到的,所以这些接口从字面意思应该是能感知到所有Aware前面的含义。

先举个BeanNameAware的例子,实现BeanNameAware接口,可以让该Bean感知到自身的BeanName(对应Spring容器的BeanId属性)属性, 举个例子:

  • BeanNameAware接口的定义

    public interface BeanNameAware extends Aware {
          void setBeanName(String name);
    }
    
  • 定义两个User,一个实现BeanNameAware,一个不实现。

    import org.springframework.beans.factory.BeanNameAware;
    
    /**
     * Created by jetty on 18/1/31.
     */
    public class User implements BeanNameAware{
    
        private String id;
    
        private String name;
    
        private String address;
    
        public void setBeanName(String beanName) {
            //ID保存BeanName的值
            id=beanName;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id='" + id + '\'' +
                    ", name='" + name + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
    import org.springframework.beans.factory.BeanNameAware;
    
    /**
     * Created by jetty on 18/1/31.
     */
    public class User2 {
    
        private String id;
    
        private String name;
    
        private String address;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id='" + id + '\'' +
                    ", name='" + name + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
  • 在Spring配置文件中初始化两个对象。

    	<bean id="zhangsan"  class="com.github.jettyrun.springinterface.demo.aware.beannameaware.User">
            <property name="name" value="zhangsan"></property>
            <property name="address" value="火星"></property>
        </bean>
    
        <bean id="lisi"  class="com.github.jettyrun.springinterface.demo.aware.beannameaware.User2">
            <property name="name" value="lisi"></property>
            <property name="address" value="火星"></property>
        </bean>
    
  • main方法测试一下BeanNameAware接口所起的作用。

    public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application-beanaware.xml");
    
            User user=context.getBean(User.class);
            System.out.println(String.format("实现了BeanNameAware接口的信息BeanId=%s,所有信息=%s",user.getId(),user.toString()));
    
            User2 user2=context.getBean(User2.class);
            System.out.println(String.format("未实现BeanNameAware接口的信息BeanId=%s,所有信息=%s",user2.getId(),user2.toString()));
        }
    
  • 运行结果

    实现了BeanNameAware接口的信息BeanId=zhangsan,所有信息=User{id='zhangsan', name='zhangsan', address='火星'}
    未实现BeanNameAware接口的信息BeanId=null,所有信息=User{id='null', name='lisi', address='火星'}
    

能够看到,我们在实现了BeanNameAware的 User中,获取到了Spring容器中的BeanId(对应spring配置文件中的id属性),而没有实现BeanNameAware的User2,则不能获取到Spring容器中的Id属性。

所以BeanNameAware接口是为了让自身Bean能够感知到,获取到自身在Spring容器中的id属性。

同理,其他的Aware接口也是为了能够感知到自身的一些属性。
比如实现了ApplicationContextAware接口的类,能够获取到ApplicationContext,实现了BeanFactoryAware接口的类,能够获取到BeanFactory对象。

IOC源码流程

spring框架的扩展性

  1. 对象实例化前添加某些功能

  2. 对象初始化前后添加某些功能

  3. 在不同的阶段发出不同的事件,完成一些功能

  4. 面向接口编程

简单脉络图:

在这里插入图片描述

  1. ApplicationContext容器入口,先getEnvironment解析properties/yml等系统环境变量,System.getProperty(),返回StandardEnvironment对象,代码中可以通过SpeL表达式获取环境变量(@Value,$#{})。

  2. AbstractApplicationContext的refresh方法,ioc的核心流程:

    	@Override
    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			// 环境设置等
    			prepareRefresh();
    
    			// 创建Bean工厂,读取xml,注解
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// 给Bean工厂设置组件
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// 扩展BeanFactory,空函数
    				postProcessBeanFactory(beanFactory);
    
    				// BeanFactoryPostProcessor扩展,可实例化Bean前修改BeanDefinition信息
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// BeanPostProcessor扩展,Bean初始化前后
    				registerBeanPostProcessors(beanFactory);
    
    				// 国际化配置,i18n
    				initMessageSource();
    
    				// 监听事件,指完成操作后触发某些功能,观察者模式
    				initApplicationEventMulticaster();
    
    				// Initialize other special beans in specific context subclasses.
    				onRefresh();
    
    				// Check for listener beans and register them.
    				registerListeners();
    
    				// 实例初始化完成,解决循环依赖问题
    				finishBeanFactoryInitialization(beanFactory);
    
    				// Last step: publish corresponding event.
    				finishRefresh();
    			}
                
                catch (BeansException ex) {
    
                    // 清空销毁
    				// Destroy already created singletons to avoid dangling resources.
    				destroyBeans();
    
    				// Reset 'active' flag.
    				cancelRefresh(ex);
    
    				// Propagate exception to caller.
    				throw ex;
    			}
    
  3. 创建Bean工厂,loadBeanDefinitions()方法,实现BeanDefinitionReader接口,然后读取xml、注解或者其他形式的Bean信息,解析封装成BeanDefinition对象,存放到beanDefinitionMap。

    容器底层是如下的ConcurrentHashMap:

在这里插入图片描述

BeanDefinition对象内容,通过xml或者注解表示,Bean的信息:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	void setParentName(@Nullable String parentName);

	@Nullable
	String getParentName();

	void setBeanClassName(@Nullable String beanClassName);

	@Nullable
	String getBeanClassName();

	void setScope(@Nullable String scope);

	@Nullable
	String getScope();

	void setLazyInit(boolean lazyInit);
    
	boolean isLazyInit();

	void setDependsOn(@Nullable String... dependsOn);

	@Nullable
	String[] getDependsOn();

	void setAutowireCandidate(boolean autowireCandidate);

	boolean isAutowireCandidate();

	void setPrimary(boolean primary);

	boolean isPrimary();

	void setFactoryBeanName(@Nullable String factoryBeanName);

	@Nullable
	String getFactoryBeanName();

	void setFactoryMethodName(@Nullable String factoryMethodName);
    
	@Nullable
	String getFactoryMethodName();
    
	ConstructorArgumentValues getConstructorArgumentValues();

	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	MutablePropertyValues getPropertyValues();

	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	void setInitMethodName(@Nullable String initMethodName);

	@Nullable
	String getInitMethodName();

	void setDestroyMethodName(@Nullable String destroyMethodName);

	@Nullable
	String getDestroyMethodName();

	void setRole(int role);

	int getRole();
    
	void setDescription(@Nullable String description);

	@Nullable
	String getDescription();

	ResolvableType getResolvableType();

	boolean isSingleton();

	boolean isPrototype();

	boolean isAbstract();

}
  1. invokeBeanFactoryPostProcessors(beanFactory);,BeanFactoryPostProcessor扩展,可以在实例化Bean前修改BeanDefinition信息。

  2. BeanFactory内部实例化bean之后,在要初始化bean对象之前,增加了一个一系列aware接口,将它的容器,以及工厂都暴露出来供使用者自由支配做扩展用,也就是可以注入到实现了aware接口的类中。

  3. 经过一些列容器以及容器对象的注入之后,在初始化之前,spring又增加了一个接口 beanPostProcessor,该接口是可以作用于所有创建的bean,在初始化前后,均能通过重写该接口获取bean对象进行定制操作。

  4. 设置国际化配置,注册事件,利用三级缓存解决循环依赖问题,利用反射,构造器实例化,注入到对应对象的属性,完成初始化功能。

  5. 经过实现销毁接口disposableBean结束其生命。

BeanFactoryPostProcessor扩展接口:

@FunctionalInterface
public interface BeanFactoryPostProcessor {

    // 实例化前
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

BeanPostProcessor扩展接口:

public interface BeanPostProcessor {

    //Bean初始化前
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

    //Bean初始化后
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

Bean的生命周期

BeanFactory源码注释:

/** 
 * <p>Bean factory implementations should support the standard bean lifecycle interfaces
 * as far as possible. The full set of initialization methods and their standard order is:
 * <ol>
 * <li>BeanNameAware's {@code setBeanName}
 * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
 * <li>BeanFactoryAware's {@code setBeanFactory}
 * <li>EnvironmentAware's {@code setEnvironment}
 * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
 * <li>ResourceLoaderAware's {@code setResourceLoader}
 * (only applicable when running in an application context)
 * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
 * (only applicable when running in an application context)
 * <li>MessageSourceAware's {@code setMessageSource}
 * (only applicable when running in an application context)
 * <li>ApplicationContextAware's {@code setApplicationContext}
 * (only applicable when running in an application context)
 * <li>ServletContextAware's {@code setServletContext}
 * (only applicable when running in a web application context)
 * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
 * <li>InitializingBean's {@code afterPropertiesSet}
 * <li>a custom init-method definition
 * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
 * </ol>
 *
 * <p>On shutdown of a bean factory, the following lifecycle methods apply:
 * <ol>
 * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
 * <li>DisposableBean's {@code destroy}
 * <li>a custom destroy-method definition
 * </ol>
 */

Bean的构造过程:

在这里插入图片描述

文字描述:

  1. Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
  2. Bean实例化后对将Bean的引入和值注入到Bean的属性中
  3. 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
  4. 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
  5. 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
  6. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()(in ne suo l z tion)方法。
  7. 如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
  8. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
  9. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
  10. 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

Bean的作用域

Spring中的bean默认都是单例的,对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框架之后,每个Action都是单例的,那么对于Spring托管的单例Service Bean,如何保证其安全呢? **Spring的单例是基于BeanFactory也就是Spring容器的,单例Bean在此容器内只有一个,Java的单例是基于 JVM,每个 JVM 内只有一个实例。**可通过Scope指定作用域。

  • singleton,单例,在Spring容器中仅存在一个Bean的实例,Bean以单例方式存在,默认值。
  • prototype,多例,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new xxxBean()。
  • request,每次HTTP请求创建一个新的Bean,该作用域仅适用于WebApplicationContext环境。
  • session,同一个HTTP Session 共享一个Bean,不同的Session使用不同的Bean,仅适用于WebApplicationContext环境。
  • 一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/334234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

专家说年轻人工资低是能力不行….

我们国家的很多专家总讲究语不惊人死不休&#xff0c;同时他们还很喜欢话风高速原地调头。 最近又有一个碉堡了的专家在大放厥词&#xff0c;就在前几天的首届长白山高峰论坛上中航基金副总经理邓海清发表批评年轻人的言论&#xff0c;邓老板是这么说的&#xff1a;很多年轻人…

数据分析实战项目3:RFM用户分群

目录1、RFM模型介绍2、Excel实际RFM划分案例3、RFM案例3.1 数据加载和基本信息查看3.2 数据预处理和RFM的初始值计算3.3 RFM区间和划分和分值计算3.4 RFM计算结果保存3.4.1 保存到excel3.4.2 保存到数据库3.5 RFM计算结果可视化3.6 结果分析&#xff08;营销建议&#xff09;3.…

[docker]笔记-基础配置

1、docker启动和设置开机启动 [rootlocalhost ~]# systemctl start docker [rootlocalhost ~]# systemctl enable docker 2、更换docker镜像网站&#xff0c;默认docker镜像网站是国外网站&#xff0c;下载镜像非常慢&#xff0c;需要更换为国内网站&#xff0c;以阿里云为例…

android多渠道打包(只编译一次)

众所周知&#xff0c;android 默认工具gradle可以配置多个productFlavors&#xff0c;以此实现配置多个不同版本&#xff0c;渠道的app应用&#xff0c;笔者认为这个编译速度很慢&#xff0c;于是乎有了今天的方案。希望能抛砖引玉为大家带来不一样的思路&#xff0c;废话不多说…

基于蜣螂算法改进的DELM预测-附代码

基于蜣螂算法改进的深度极限学习机DELM的回归预测 文章目录基于蜣螂算法改进的深度极限学习机DELM的回归预测1.ELM原理2.深度极限学习机&#xff08;DELM&#xff09;原理3.蜣螂算法4.蜣螂算法改进DELM5.实验结果6.参考文献7.Matlab代码1.ELM原理 ELM基础原理请参考&#xff1…

QT基础入门【布局篇】消除控件之间的间隔

一、相关参数 layoutLeftMargin: layout内的布局距离边框左端的距离。 layoutTopMargin: layout内的布局距离边框顶端的距离。 layoutRightMargin: layout内的布局距离边框右端的距离。 layoutBottomMargin: layout内的布局距离边框底端的距离。 layoutHorizontalSpacing: layo…

【每日阅读】前端了解的HTTP协议知识(二)

HTTP 简介 HTTP 协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写,是用于从万维网&#xff08;WWW:World Wide Web &#xff09;服务器传输超文本到本地浏览器的传送协议&#xff1b; HTTP工作原理 HTTP协议工作于客户端-服务端架构上&#xf…

算法导论—近似算法

近似算法基础1. 近似算法的基本概念2. 近似算法的性能分析1. 近似算法的基本概念 很多实际应用问题都是NP-完全问题&#xff0c;这类问题很可能不存在多项式时间算法。一般而言&#xff0c;NP-完全问题可采用以下三种方式处理。 如果问题的输入规模较小&#xff0c;则可以利用…

利用IO工具包拷贝文件夹或者文件

引入依赖 <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version> </dependency> code 拷贝文件夹 PostMapping("/findB00List") CrossOrigin public Result …

(考研湖科大教书匠计算机网络)第三章数据链路层-第十节:以太网交换机的生成树协议STP

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;以太网故障导致的网络问题二&#xff1a;利用冗余链路提高稳定性&#xff08;1&#xff09;概述&#xff08;2&#xff09;冗余链路带来的问题三&a…

Swagger2 3.0的使用

前言 今天使用了以下swagger2 的3.0.0版本&#xff0c;好家伙&#xff0c;好多坑。在这里记录一下&#xff0c;方便查阅。 一、Swagger的简介 官网&#xff1a;https://swagger.io/ Swagger 是一个规范且完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的…

应用监控以及告警实现

前言 一个Java应用 可以不优秀&#xff0c;但是一定不能没有监控方案。否则极大影响排查线上问题的效 以及系统故障的及时告警 。试想 核心应用挂了一个 但是没有配置告警 理想情况几个小时 被自己人发现了 但是万一自己人也没看到或者没关注 那难道让服务一直挂下去么 &#…

Vue框架学习篇(五)

Vue框架学习篇(五) 1 组件 1.1 组件的基本使用 1.1.1 基本流程 a 引入外部vue组件必须要的js文件 <script src"../js/httpVueLoader.js"></script>b 创建.vue文件 <template><!--公共模板内容--></template><script><!…

LaoCat带你认识容器与镜像(实践篇二上)

实践篇主要以各容器的挂载和附加命令为主。 本章内容 本文实操全部基于Ubuntu 20.04 宿主机 > linux服务器本身 Docker > 20.10.22 在开始本章内容之前&#xff0c;我解答一个问题&#xff0c;有小伙伴问我说&#xff0c;有的容器DockerHub官网并没有提供任何可参考的文…

可信AI年度观察 | 智能语音产业需求不断升级,评测重点由技术转向产品

自《新一代人工智能发展规划》发布以来&#xff0c;人工智能发展已上升为国家战略&#xff0c;在“十四五”规划中&#xff0c;更是将人工智能列为科技前沿领域的“最高优先级”&#xff0c;国家政策支持为人工智能产业发展提供良好环境。同时&#xff0c;各行业逐渐重视改善价…

ChatGPT 支持的搜索引擎 Bing 究竟什么样?

微软于2月8日北京时间凌晨在 Redmond 线下举办一场媒体活动&#xff0c;围绕微软的产品以及 AI&#xff0c;公布最新消息。这里我们先回顾一下微软在 AI 上的布局。 2019年&#xff0c;微软向 OpenAI 投资10亿美元&#xff0c;成为了 OpenAI 紧密的合作伙伴&#xff0c;而微软…

Git学习笔记-详细使用教程

一、定义 Git&#xff08;读音为/gɪt/&#xff09;是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的。 二、Git与SVN的最主要的区别&#xff1f; SVN是集中式版本控制系统&#xff0c;版本库是集中放在中央服务器的&#xff0c;而干活的时…

分享:提升你工作幸福感的11个工具软件!

今天给大家分享11个非常好用的资源、工具网站。不论你是做运营、设计&#xff0c;还是个人生活中的应用&#xff0c;甚至只是提升你在线冲浪的快乐感&#xff0c;你都值得拥有它们。 1&#xff0c;在线一键抠图 https://www.remove.bg/ 免费的软件&#xff0c;自动抠图&…

【官方 | 计算机二级Python教程】第八章:Python计算生态

【官方 | 计算机二级Python教程】第八章&#xff1a;Python计算生态参考书目第八章&#xff1a;Python计算生态本章知识导图8.1 计算思维8.2 程序设计方法论8.3 计算生态与生态式编程8.4 基本的Python内置函数习题本文代码编译环境及版本更新日志参考书目 拜读的是计算机等级考…

mysql安装指定版本详细教程mysql 8.0.28示例

之前出过一版安装mysql5.7和安装mysql8.x最新版本的文档今天根据需求出一版指定版本的安装教程以8.0.28为例https://dev.mysql.com/downloads/mysql/ 下载mysql的官网下载好后上传到服务器安装时会报错公钥URL错误rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 …