spring bean注入方式
構造器注入
<!--構造器注入-->
<bean id="user" class="com.sean.spring.User">
<constructor-arg index="0" value="德萊文"/>
<constructor-arg index="1" value="18"/>
</bean>
setter注入
<!--setter注入-->
<bean id="user" class="com.sean.spring.User">
<property name="name" value="無敵"></property>
<property name="age" value="18"></property>
</bean>
如果我們一個類中多個參數,那麼我們要賦值豈不是通過以上兩種方法要寫很多,除了通過xml注入,還可以通過註解的方式注入注入。
context:annotation-config ,用於激活那些已經在spring容器裏註冊過的bean
<context:annotation-config></context:annotation-config>
<bean id="user" class="com.sean.spring.User"/>
然後在類中需要注入值的屬性上添加@Autowired,如果需要設置,可通過 @Value直接給值
@Autowired
@Value("無敵")
public void setName(String name) {
this.name = name;
}
@Autowired
@Value("25")
public void setAge(Integer age) {
this.age = age;
}
當然項目中有很多類,通過這種方式,豈不是也要配置很多的bean,別怕,Spring提供了掃描包的方式。
context:component-scan自動將帶有@component,@service,@Repository等註解的對象註冊到spring容器中的功能。
<context:component-scan base-package="com.sean.spring" />
只需在類中添加@Component
@Component
public class User{
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
@Autowired
@Value("無敵")
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getUser(){
String user = "我的名字是"+ name+"我今年" + age+"歲";
return user;
}
}
測試後輸出:
我們將applicationContext.xml配置文件作如下修改:
關於spring配置註解context:annotation-config
和context:component-scan
區別,網上很多博客都有講解
https://www.cnblogs.com/leiOOlei/p/3713989.html
Spring bean 的生命週期
- 如果Bean實現了
BeanNameAware
的setBeanName
方法,那麼它就會調用這個方法。 - 如果Bean實現了
BeanFactoryAware
的setBeanFactory
方法,那麼它就會調用這個方法。 - 如果Bean實現了
ApplicationContextAware
的setApplicationContext
方法,且Spring IoC容器也必須是一個ApplicationContext
接口的實現類,那麼纔會調用這個接口,否則不調用 - 如果Bean實現了
BeanPostProcessor
的postProcessBeforeInitialization
方法,那麼它就會調用這個方法。 - 如果Bean實現了
InitializingBean
的afterPropertiesSet
方法,那麼它就會調用這個方法。 - 如果Bean自定義了初始化方法,那麼它就會調用這個方法。
- 如果Bean實現了
BeanPostProcessor
的postProcessAfterInitialization
方法,完成這些調用,這時候Bean就完成了初始化 - 當服務器關閉,調用對應額方法完成Bean的銷燬
- 如果Bean實現了
DisposableBean
的destroy
方法,那麼它就會調用這個方法。 - 如果自定義銷燬對象,那麼就會調用它。
下邊我們來測試一下,先測試一下BeanPostProcessor
接口。
我們下一個實現類BeanPostProcessorImpl
public class BeanPostProcessorImpl implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【"+this.getClass().getSimpleName()+"】"+beanName + "開始實例化");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【"+this.getClass().getSimpleName()+"】"+beanName + "實例化完成");
return bean;
}
}
這樣一個BeanPostProcessor
就被我們用代碼實現了,它會處理Spring IoC容器所有的Bean
測試生命週期
public class User implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void init(){
System.out.println("【"+this.getClass().getSimpleName()+"】" + "執行自定義初始化方法");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("【"+this.getClass().getSimpleName()+"】" + "setBeanFactory");
}
public String getUser(){
String user = "我的名字是"+ name+"我今年" + age+"歲";
return user;
}
public void setBeanName(String s) {
System.out.println("【"+this.getClass().getSimpleName()+"】"+ "setBeanName");
}
public void myDestroy() throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】"+ "自定義銷燬");
}
public void destroy() throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】"+ "destroy");
}
public void afterPropertiesSet() throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】" + "afterPropertiesSet");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("【"+this.getClass().getSimpleName()+"】"+ "setApplicationContext");
}
}
這個類實現了所有生命週期所能實現的方法,以便於觀察生命週期的過程,其中init
方法是自定義初始化方法,myDestroy
方法是自定義銷燬方法。
我們修改配置文件spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="beanPostProcessor" class="com.sean.spring.BeanPostProcessorImpl"/>
<!--setter注入-->
<bean id="user" class="com.sean.spring.User" init-method="init" destroy-method="myDestroy">
<property name="name" value="無敵"></property>
<property name="age" value="18"></property>
</bean>
</beans>
寫一個測試類,看一下結果
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring/spring-config.xml");
User user = context.getBean(User.class);
logger.debug(user.getUser());
((ClassPathXmlApplicationContext) context).close();
}
打印日誌:
在項目或者面試中,經常會碰到Spring 循環依賴問題,從源碼解決Spring 循環依賴問題