spring annotation

Spring1

一、spring的IOC container(1)

    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在部署的時候容器不會自動檢測是否存在

spring的scope

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以下圖



prototype以下圖:


可是在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,感謝博主)


Request Scope

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>
相關文章
相關標籤/搜索