7.修改BeanDefinition
Spring IOC在實(shí)例化Bean對象之前,需要先讀取Bean的相關(guān)屬性,保存到BeanDefinition
對象中,然后通過BeanDefinition對象,實(shí)例化Bean對象。
如果想修改BeanDefinition對象中的屬性,該怎么辦呢?
答:我們可以實(shí)現(xiàn)BeanFactoryPostProcessor
接口。
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder.addPropertyValue("id", 123);
beanDefinitionBuilder.addPropertyValue("name", "蘇三說技術(shù)");
defaultListableBeanFactory.registerBeanDefinition("user", beanDefinitionBuilder.getBeanDefinition());
}
}
在postProcessBeanFactory方法中,可以獲取BeanDefinition的相關(guān)對象,并且修改該對象的屬性。
8.初始化Bean前后
有時(shí),你想在初始化Bean前后,實(shí)現(xiàn)一些自己的邏輯。
這時(shí)可以實(shí)現(xiàn):BeanPostProcessor
接口。
該接口目前有兩個(gè)方法:
- postProcessBeforeInitialization 該在初始化方法之前調(diào)用。
- postProcessAfterInitialization 該方法再初始化方法之后調(diào)用。
例如:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof User) {
((User) bean).setUserName("蘇三說技術(shù)");
}
return bean;
}
}
如果spring中存在User對象,則將它的userName設(shè)置成:蘇三說技術(shù)。
其實(shí),我們經(jīng)常使用的注解,比如:@Autowired、@Value、@Resource、@PostConstruct等,是通過AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor實(shí)現(xiàn)的。
9.初始化方法
目前spring中使用比較多的初始化bean的方法有:
- 使用@PostConstruct注解
- 實(shí)現(xiàn)InitializingBean接口
9.1 使用@PostConstruct注解
@Service
public class AService {
@PostConstruct
public void init() {
System.out.println("===初始化===");
}
}
在需要初始化的方法上增加@PostConstruct
注解,這樣就有初始化的能力。
9.2 實(shí)現(xiàn)InitializingBean接口
@Service
public class BService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("===初始化===");
}
}
實(shí)現(xiàn)InitializingBean
接口,重寫afterPropertiesSet
方法,該方法中可以完成初始化功能。
10.關(guān)閉容器前
有時(shí)候,我們需要在關(guān)閉spring容器前,做一些額外的工作,比如:關(guān)閉資源文件等。
這時(shí)可以實(shí)現(xiàn)DisposableBean
接口,并且重寫它的destroy
方法:
@Service
public class DService implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean afterPropertiesSet");
}
}
這樣spring容器銷毀前,會調(diào)用該destroy方法,做一些額外的工作。
通常情況下,我們會同時(shí)實(shí)現(xiàn)InitializingBean和DisposableBean接口,重寫初始化方法和銷毀方法。
11.自定義作用域
我們都知道spring默認(rèn)支持的Scope
只有兩種:
- singleton 單例,每次從spring容器中獲取到的bean都是同一個(gè)對象。
- prototype 多例,每次從spring容器中獲取到的bean都是不同的對象。
spring web又對Scope進(jìn)行了擴(kuò)展,增加了:
- RequestScope 同一次請求從spring容器中獲取到的bean都是同一個(gè)對象。
- SessionScope 同一個(gè)會話從spring容器中獲取到的bean都是同一個(gè)對象。
即便如此,有些場景還是無法滿足我們的要求。
比如,我們想在同一個(gè)線程中從spring容器獲取到的bean都是同一個(gè)對象,該怎么辦?
這就需要自定義Scope了。
第一步實(shí)現(xiàn)Scope接口:
public class ThreadLocalScope implements Scope {
private static final ThreadLocal THREAD_LOCAL_SCOPE = new ThreadLocal();
@Override
public Object get(String name, ObjectFactory> objectFactory) {
Object value = THREAD_LOCAL_SCOPE.get();
if (value != null) {
return value;
}
Object object = objectFactory.getObject();
THREAD_LOCAL_SCOPE.set(object);
return object;
}
@Override
public Object remove(String name) {
THREAD_LOCAL_SCOPE.remove();
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return null;
}
}
第二步將新定義的Scope注入到spring容器中:
@Component
public class ThreadLocalBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerScope("threadLocalScope", new ThreadLocalScope());
}
}
第三步使用新定義的Scope:
@Scope("threadLocalScope")
@Service
public class CService {
public void add() {
}
}
-
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14338 -
AOP
+關(guān)注
關(guān)注
0文章
40瀏覽量
11098 -
IOC
+關(guān)注
關(guān)注
0文章
28瀏覽量
10099
發(fā)布評論請先 登錄
相關(guān)推薦
評論