org.springframework.beans org.springframework.context构成了springIoc的容器核心框架
1.1FactoryBean 这个接口是spring的创建类的所需要实现的接口
创建一个类
T getObject() throws Exception;
返回创建类的class
Class<?> getObjectType();
判断创建类是否为单例
boolean isSingleton();
1.2 BeanFactory 这个接口是spring对外提供可以配置的管理机制,管理任何类型的对象
//工厂对象的前缀 String FACTORY_BEAN_PREFIX = "&"; //根据名字获取的对象instance Object getBean(String name) throws BeansException; //根据名字和类型获取对象instance <T> T getBean(String name, Class<T> requiredType) throws BeansException; /根据类型获取一个类instance <T> T getBean(Class<T> requiredType) throws BeansException; //根据名字和构造器的参数(或者工厂方法的参数)返回一个类instance Object getBean(String name, Object... args) throws BeansException; //根据类型和和构造器的参数(或者工厂方法的参数)返回一个类instance <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; //根据名字(bean definition name)判断是否含有一个类instance 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对象 Class<?> getType(String name) throws NoSuchBeanDefinitionException; //根据一个定义名字返回这个类的所有别名组成的数组 String[] getAliases(String name);
如下图是它的一个核心子类ApplicationContext
The interface org.springframework.context.ApplicationContext represents the Spring IoC
container and is responsible for instantiating, configuring, and assembling the aforementioned beans.
它是代表了spring ioc容器 初始化 配置 装载 它管理的bean
一个spring管理类的元数据定义有XML文件和注解两种方法,其中注解有分为Annotation-based configuration(spring自带的注解)和Java-based configuration(jdk自带注解@Configuration, @Bean, @Import and @DependsOn annotations)
.
XML配置
可以支持导入,以便按照实际需求拆分定义bean,如下:
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
ApplicationContext 可以返回想要的bean
The ApplicationContext enables you to read bean definitions and access them as follows:
// create and configure beans
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);
// use configured instance
List<String> userList = service.getUsernameList();
不提倡在系统中这样应用的获取bean,它高度耦合了Spring的代码
ApplicationContext context =new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
应使用依赖注入的办法实现松耦合!
(实质上的xml 或者注解配置的信息是元数据,它并不是spring真正使用的类)
Within the container itself, these bean definitions are represented as BeanDefinition objects, which
contain (among other information) the following metadata:
XML配置: The idref element 一、 <bean id="theTargetBean" class="..."/> <bean id="theClientBean" class="..."> <property name="targetName"> <idref bean="theTargetBean" /> </property> </bean> 二、 <bean id="theTargetBean" class="..." /> <bean id="client" class="..."> <property name="targetName" value="theTargetBean" /> </bean> 两种方法区别: idref在部署的时候spring ioc容器要对idref的类去验证,看是否存在 property在部署的时候容器不会自动检测是否存在
Scope Description
singleton (Default) Scopes a single bean definition to a
single object instance per Spring IoC container.
prototype Scopes a single bean definition to any number of
object instances.
request Scopes a single bean definition to the lifecycle
of a single HTTP request; that is, each HTTP
request has its own instance of a bean created
off the back of a single bean definition. Only
Spring Framework
57Spring Framework Reference Documentation
Scope
Description
valid in the context of a web-aware Spring
ApplicationContext.
session Scopes a single bean definition to the lifecycle of
an HTTP Session. Only valid in the context of a
web-aware Spring ApplicationContext.
global session Scopes a single bean definition to the lifecycle
of a global HTTP Session. Typically only
valid when used in a portlet context. Only
valid in the context of a web-aware Spring
ApplicationContext.
application Scopes a single bean definition to the lifecycle of
a ServletContext. Only valid in the context of
a web-aware Spring ApplicationContext.
但是在single的scope下引用prototype的时候只是会出现问题,bean的引用关系在第一次初始化的时候就会被确定,single的属性一直不会被更新,所以prototype的对象不会被更新为最新创建的对象,解决办法如下:
public abstract class Chinese implements Person { public Chinese() { System.out.pritln("Spring实例化主调bean:Chinese实例..."); } //定义一个抽象方法,该方法将由Spring负责实现 publc abstract getAxe(); public void useAxe() { System.out.println("正在使用"+getAxe()+"看菜!"); } } 为了让Spring知道如何实现该方法,我们需要在配置文件中使用<lookup-method.../>元素指定如下两个属性:name:指定需要让Spring实现的方法 bean:指定Spring实现该方法后的返回值。 <bean id="chinese" class="com.feng.service.impl.Chinese"> <!--指定getAxe方法返回steelAxe 每次调用getAxe方法将获取新的steelAxe对象--> <look-method name="getAxe" bean="steelAxe"/> --> </bean> 上面的代码指定Spring将负责实现getAxe()方法,该方法的返回值是容器中的steelAxe Bean实例。 (引用自博客:http://blog.csdn.net/howlaa/article/details/8332519,感谢博主)
If you access scoped beans within Spring Web MVC, in effect, within a request that is processed
by the Spring DispatcherServlet, or DispatcherPortlet, then no special setup is necessary:
DispatcherServlet and DispatcherPortlet already expose all relevant state.
使用DispatcherServlet代理的类都是request scope
注意:
If you use a Servlet 2.5 web container, with requests processed outside of
Spring’s DispatcherServlet (for example, when using JSF or Struts), you need
to register the org.springframework.web.context.request.RequestContextListener
ServletRequestListener.
使用Servlet 2.5 web需要使用该RequestContextListener进行转换!
LifeCycle
(图片摘自:http://developer.51cto.com/art/201104/255961.htm 感谢博主! )
一、spring Bean的作用域:scope=singleton(默认,单例,生成一个实例)
二、spring Bean的作用域:scope=prototype(多线程, 生成多个实例)
三、单例模式,默认在程序初始化的时候实例化(lazy-init="false")
四、prototype,getBean的时候才是实例化
五、lazy-init 只对单例模式起作用,对 prototype 不起作用(因为 prototype 默认就不是程序初始化的时候实例化的)
1.容器寻找Bean的定义信息并且将其实例化。
2.受用依赖注入,Spring按照Bean定义信息配置Bean的所有属性。
3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
4.如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
5.如果BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialzation()方法将被调用。
6.如果Bean指定了init-method方法,它将被调用。
7.最后,如果有BeanPsotProcessor和Bean关联,那么它们的postProcessAfterInitialization()方法将被调用。
到这个时候,Bean已经可以被应用系统使用了,并且将被保留在Bean Factory中知道它不再需要。
有两种方法可以把它从Bean Factory中删除掉。
1.如果Bean实现了DisposableBean接口,destory()方法被调用。
2.如果指定了订制的销毁方法,就调用这个方法。
Bean在Spring应用上下文的生命周期与在Bean工厂中的生命周期只有一点不同,
唯一不同的是,如果Bean实现了ApplicationContextAwre接口,setApplicationContext()方法被调用。
只有singleton行为的bean接受容器管理生命周期。
non-singleton行为的bean,Spring容器仅仅是new的替代,容器只负责创建。
对于singleton bean,Spring容器知道bean何时实例化结束,何时销毁,
Spring可以管理实例化结束之后,和销毁之前的行为,管理bean的生命周期行为主要未如下两个时机:
Bean全部依赖注入之后
Bean即将销毁之前
1)依赖关系注入后的行为实现:
有两种方法:A.编写init方法 B.实现InitializingBean接口
afterPropertiesSet和init同时出现,前者先于后者执行,使用init方法,需要对配置文件加入init-method属性
2)bean销毁之前的行为
有两种方法:A.编写close方法 B.实现DisposableBean接口
destroy和close同时出现,前者先于后者执行,使用close方法,需要对配置文件加入destroy-method属性
(摘自:http://blog.csdn.net/java958199586/article/details/7469147,感谢博主!)
清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责!
生命周期就是springIOC容器在初始化一个bean的时候的预留一些接口,(每个时期都有有三个等级:Bean级别,BeanFactory级别:,Application级别)
自定义的Bean不到万不得已不要直接引用Spring API产生耦合,这是种下一个孽缘,会有恶果的,能用注解用注解,这才是善缘。
如果你想修改一个spring ioc 并未对外暴露的api,可以通过集成一个BeanPostProcessor来达到目的,同理可以修改BeanFactory
a BeanPostProcessor yourself. For more information, see Section 5.8, “Container Extension Points
/**
* Factory hook that allows for custom modification of new bean instances,
* e.g. checking for marker interfaces or wrapping them with proxies.
*
* <p>ApplicationContexts can autodetect BeanPostProcessor beans in their
* bean definitions and apply them to any beans subsequently created.
* Plain bean factories allow for programmatic registration of post-processors,
* applying to all beans created through this factory.
*
* <p>Typically, post-processors that populate beans via marker interfaces
* or the like will implement {@link #postProcessBeforeInitialization},
* while post-processors that wrap beans with proxies will normally
* implement {@link #postProcessAfterInitialization}.
*
* @author Juergen Hoeller
* @since 10.10.2003
* @see InstantiationAwareBeanPostProcessor
* @see DestructionAwareBeanPostProcessor
* @see ConfigurableBeanFactory#addBeanPostProcessor
* @see BeanFactoryPostProcessor
*/
public interface BeanPostProcessor {
/**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one; if
* {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding {@code bean instanceof FactoryBean} checks.
* <p>This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other BeanPostProcessor callbacks.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one; if
* {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
/**
* Allows for custom modification of an application context's bean definitions,
* adapting the bean property values of the context's underlying bean factory.
*
* <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
* their bean definitions and apply them before any other beans get created.
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context.
*
* <p>See PropertyResourceConfigurer and its concrete implementations
* for out-of-the-box solutions that address such configuration needs.
*
* <p>A BeanFactoryPostProcessor may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* @author Juergen Hoeller
* @since 06.07.2003
* @see BeanPostProcessor
* @see PropertyResourceConfigurer
*/
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
由衷赞叹的spring设计如此之灵活,可扩展性如此之高啊,顶礼膜拜!(可以借鉴到自己的代码之中)
初始化:
public interface InitializingBean {
/**
* Invoked by a BeanFactory after it has set all bean properties supplied
* (and satisfied BeanFactoryAware and ApplicationContextAware).
* <p>This method allows the bean instance to perform initialization only
* possible when all bean properties have been set and to throw an
* exception in the event of misconfiguration.
* @throws Exception in the event of misconfiguration (such
* as failure to set an essential property) or if initialization fails.
*/
void afterPropertiesSet() throws Exception;
}
(@PostConstruct) 初始化的接口(注解) init-method
销毁:
public interface DisposableBean {
/**
* Invoked by a BeanFactory on destruction of a singleton.
* @throws Exception in case of shutdown errors.
* Exceptions will get logged but not rethrown to allow
* other beans to release their resources too.
*/
void destroy() throws Exception;
}
(@PreDestroy)销毁的接口(注解) destroy-method
给一个bean注入一个ApplicationContext
public interface ApplicationContextAware extends Aware {
/**
* Set the ApplicationContext that this object runs in.
* Normally this call will be used to initialize the object.
* <p>Invoked after population of normal bean properties but before an init callback such
* as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
* or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
* {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
* {@link MessageSourceAware}, if applicable.
* @param applicationContext the ApplicationContext object to be used by this object
* @throws ApplicationContextException in case of context initialization errors
* @throws BeansException if thrown by application context methods
* @see org.springframework.beans.factory.BeanInitializationException
*/
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
给一个Bean注入创建他的工厂
public interface BeanFactoryAware extends Aware {
/**
* Callback that supplies the owning factory to a bean instance.
* <p>Invoked after the population of normal bean properties
* but before an initialization callback such as
* {@link InitializingBean#afterPropertiesSet()} or a custom init-method.
* @param beanFactory owning BeanFactory (never {@code null}).
* The bean can immediately call methods on the factory.
* @throws BeansException in case of initialization errors
* @see BeanInitializationException
*/
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
给一个bean注入他自己的内存注册的ID
public interface BeanNameAware extends Aware {
/**
* Set the name of the bean in the bean factory that created this bean.
* <p>Invoked after population of normal bean properties but before an
* init callback such as {@link InitializingBean#afterPropertiesSet()}
* or a custom init-method.
* @param name the name of the bean in the factory.
* Note that this name is the actual bean name used in the factory, which may
* differ from the originally specified name: in particular for inner bean
* names, the actual bean name might have been made unique through appending
* "#..." suffixes. Use the {@link BeanFactoryUtils#originalBeanName(String)}
* method to extract the original bean name (without suffix), if desired.
*/
void setBeanName(String name);
}
这样的做法还是不好滴,因为又产生了spring的依赖,spring 2.5以后可以支持@Autowired这个注解,所以,spring一直提倡在自己代码内不要直接依赖springAPI,不然注解,不然xml配置!
<bean id="inheritedTestBeanWithoutClass" abstract="true"> <property name="name" value="parent"/> <property name="age" value="1"/> </bean> <bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBeanWithoutClass" init-method="initialize"> <property name="name" value="override"/> <!-- age will inherit the value of 1 from the parent bean definition--> </bean>
spring的继承配置,当父类配置为abstract="true" 仅仅能被当天的xml模板使用,不能被初始化长生实体类,也不能被当作ref去被别的类引用,会报错的被引用了
Customizing instantiation logic with a FactoryBean
如果你的类初始化需要大量工作流程,过于复杂,不用担心,Spring IOC为你准备了FactoryBean,只有实现此接口你便可以随心所欲创造你的类,不需要在xml配置那么多的元算,如此优雅配置即可:
<bean id="factoryBeanOne" class="com.study.demo.factorybean.SimpleFactoryBean" > </Bean>