org.springframework.beans org.springframework.context構成了springIoc的容器核心框架java
1.1FactoryBean 這個接口是spring的建立類的所須要實現的接口web
建立一個類
spring
T getObject() throws Exception;
返回建立類的classapi
Class<?> getObjectType();
判斷建立類是否爲單例數組
boolean isSingleton();
1.2 BeanFactory 這個接口是spring對外提供能夠配置的管理機制,管理任何類型的對象session
//工廠對象的前綴 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.app
它是表明了spring ioc容器 初始化 配置 裝載 它管理的bean
框架
一個spring管理類的元數據定義有XML文件和註解兩種方法,其中註解有分爲Annotation-based configuration(spring自帶的註解)和Java-based configuration(jdk自帶註解@Configuration, @Bean, @Import and @DependsOn annotations)ide
.
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 1、 <bean id="theTargetBean" class="..."/> <bean id="theClientBean" class="..."> <property name="targetName"> <idref bean="theTargetBean" /> </property> </bean> 2、 <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 感謝博主! )
1、spring Bean的做用域:scope=singleton(默認,單例,生成一個實例)
2、spring Bean的做用域:scope=prototype(多線程, 生成多個實例)
3、單例模式,默認在程序初始化的時候實例化(lazy-init="false")
4、prototype,getBean的時候纔是實例化
5、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>