Spring Core
在一個生命周期長的對象裡面定義一個scope
為request
,或session
的對象
- xml配置方式
proxy-target-class
default=true
使用CGlib進行代理; default=false
時使用JDK動態代理;
<!-- DefaultUserPreferences implements the UserPreferences interface -->
<bean id="userPreferences" class="com.stuff.DefaultUserPreferences" scope="session">
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
<bean id="userManager" class="com.stuff.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>
- 註解方式
CGLIB 方式:@Scope(value="request", proxyMode= ScopedProxyMode.TARGET_CLASS)
JDK動態代理 方式:@Scope(value="request", proxyMode= ScopedProxyMode.INTERFACES)
util
標籤
未使用util標籤時 注入 constant isolation
<bean id="..." class="...">
<property name="isolation">
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>
使用util標籤可以更加簡潔
<bean id="..." class="...">
<property name="isolation">
<util:constant static-field="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
</property>
</bean>
如果一個單例bean引用了原型bean,如何保證每次單例bean中的原型bean每次都是不一樣的?
方法一:lookup
,通過lookup會自動去查找類型一樣的bean進行注入;注意使用lookup的方法必須為抽象方法;
@Component
@Scope(value = "prototype")
public class AAA {}
@Component
public abstract class ControllerManager {
private AAA aaa;
@Lookup
public abstract AAA createAAA() ;
public void test() {
this.aaa = createAAA();
System.err.println(this.getClass()+" "+this);
}
}
方法二:實現ApplicationContextAware拿到beanFactory對象,每次方法調用的時候都會獲取到一個新的單例bean
## `@Autowired` field 注入為什麼不用setter,getter方法?
- `@Autowired`先會按類型注入,如果有多個類型,則按照名字注入;
在源碼中設置值是通過反射實現`org.springframework.beans.DirectFieldAccessor.FieldPropertyHandler#setValue`
```java
@Override
public void setValue(@Nullable Object value) throws Exception {
try {
ReflectionUtils.makeAccessible(this.field);
this.field.set(getWrappedInstance(), value);
}
catch (IllegalAccessException ex) {
throw new InvalidPropertyException(getWrappedClass(), this.field.getName(),
"Field is not accessible", ex);
}
}
如果@Autowired
介面有多個子實現類,如何指定為特定的一個呢?
- 在某一個子實現類上使用
@Primary
指定要注入的Bean為當前的bean
@Primary
public class ProtoBeanImpl implements ProtoBean{
}
@Primary
@Bean
public ProtoBeanImpl protoBean(){
return new ProtoBeanImpl();
}
- 使用
@Qulifier("xxx")
註解 指定要注入的bean的類型
@Qualifier("protoBeanImpl2")
@Autowired
private ProtoBean bean;
@Autowired
public SingleBean(@Qualifier("protoBeanImpl2") ProtoBean proto) {
this.protoBeanImpl2 = (ProtoBeanImpl2) proto;
}
- 使用@Bean上的
autowireCandidate = false
指定該bean 不會被其他類自動注入
@Bean(autowireCandidate = false)
public ProtoBeanImpl protoBean(){
return new ProtoBeanImpl();
}
構造器注入
using constructor inject,do not need other annotation if all the properties is base type ,using
@ConstrutorProperties({“xxx”,”xxx”,…}) to inject the value
-
if just one constructor here ,need not
@Autowired
-
only one multi-argument constructor can be set
@Autowired(required = true)
-
if one more constructor are annotationed with
@Autowired(required = false)
The constructor with the greatest number of dependencies that can be satisfied
by matching beans in the Spring container will be chose -
The @Autowired, @Inject, @Value, and @Resource annotations are handled by Spring
BeanPostProcessor implementations
使用AspectJ註解進行AOP配置好還是xml?
使用xml配置時,將AOP配置分散了,一部分在xml中,一部分在後台的class類中。不符合DRY原則。
然而使用@AspectJ
,則將整個AOP的配置放在一個配置類中,@AspectJ支援額外的實例模型更豐富的組合,是每個切面成為一個模型單元。
同時,@AspectJ 能被 Spring AOP 和AspectJ 解析,你可以使用AspectJ的語法去實現更加複雜的切面邏輯
閉包 和 回調
閉包:閉包和匿名函數經常被用作同義詞。但嚴格來說,匿名函數就是字面意義上沒有被賦予名稱的函數,而閉包則實際上是一個函數的實例,也就是說它是存在於記憶體里的某個結構體。如果從實現上來看的話,匿名函數如果沒有捕捉自由變數,那麼它其實可以被實現為一個函數指針,或者直接內聯到調用點,如果它捕捉了自由變數那麼它將是一個閉包;而閉包則意味著同時包括函數指針和環境兩個關鍵元素。參考出處
[Closure Sample][Closure Sample]
public interface Adder {
int add(int x);
}
public static Adder makeAdder(final int n) {
return new Adder() {
public int add(int x) {
return x + n;
}
};
}
回調:在電腦程式設計中,回調函數,或簡稱回調(Callback 即call then back 被主函數調用運算後會返回主函數),是指通過參數將函數傳遞到其它程式碼的,某一塊可執行程式碼的引用參考出處
Callback Sample
class RemoteClass {
private OnChangeListener mOnChangeListener;
void makeSomeChanges() {
/*
.. do something here and call callback
*/
mOnChangeListener.onChanged(this, 1);
}
public void setOnChangeListener(OnChangeListener listener) {
mOnChangeListener = listener;
}
public interface OnChangeListener {
public void onChanged(RemoteClass remoteClass, int test);
}
}
class Test {
public static void main(String[] args) {
RemoteClass obj = new RemoteClass();
obj.setOnChangeListener(demoChanged);
obj.makeSomeChanges();
}
// this case remid me of spring framework lots of anonymous ObjectFactory call back
private static RemoteClass.OnChangeListener demoChanged = new RemoteClass.OnChangeListener() {
@Override
public void onChanged(RemoteClass remoteClass, int incoming) {
switch (incoming) {
case 1:
System.out.println("I will take appropriate action!");
break;
default:
break;
}
}
};
}
// callback in springframework 4.3.x
// @see org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
@Configurable
@Configuration
@Configuration
是配置類
@Configurable
它是一個bean所依賴的Aspect,並且不被Spring管理,但是可以自動注入