Spring Core

WhaleFall541 發表於 2021-09-15
Spring

在一個生命週期長的物件裡面定義一個scoperequest,或session的物件

  1. 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>
  1. 註解方式

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介面有多個子實現類,如何指定為特定的一個呢?

  1. 在某一個子實現類上使用@Primary指定要注入的Bean為當前的bean
@Primary 
public class ProtoBeanImpl implements ProtoBean{
}
@Primary
@Bean
public ProtoBeanImpl protoBean(){
    return new ProtoBeanImpl();
}
  1. 使用@Qulifier("xxx")註解 指定要注入的bean的型別
	@Qualifier("protoBeanImpl2")
    @Autowired
    private ProtoBean bean;
@Autowired
public SingleBean(@Qualifier("protoBeanImpl2") ProtoBean proto) {
    this.protoBeanImpl2 = (ProtoBeanImpl2) proto;
}
  1. 使用@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

  1. if just one constructor here ,need not @Autowired

  2. only one multi-argument constructor can be set @Autowired(required = true)

  3. 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

  4. 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管理,但是可以自動注入