MVCを実現する:2.bean負荷,IoC依存注入
6175 ワード
背景
前にjavaパケットのスキャンを実現し、スキャン後に自然にbeanのロードに達し、spring mvcの大きな特性IoC依存注入の実現を実現した.
ここでは,beanの負荷と依存注入の実現を以前に基づいて実現する.
デザイン
私たちが真似した車輪はspring mvcで、いくつかの複雑なシーンを簡略化して、ここでは注釈の形式だけを実現します
1.spring-mvcの使用姿勢に依存し、いくつかの注釈を定義する必要があります.クラス上注記 すべてのクラスに上記の注記があり、インスタンスが必要なbeanを表します.属性注記 このプロパティをbeanオブジェクトでインスタンス化することを示します.
2.インスタンス化bean
ClassによるBeanオブジェクトの作成
3.ロード依存
各Beanのプロパティをスキャンし、
4.beanを取得するための様々な方法を提供する
最も一般的なのはbeanName、beanタイプによってBeanを取得します
5.動的登録beanの提供
たとえば、サードパーティのjarパッケージのクラスに依存して、サードパーティのクラスを変更できないため、動的登録でbeanをロードすることもできます.
インプリメンテーション
1.注記定義
これは比較的に簡単で、直接いくつかの関連する注釈を貼ります
いくつかの宣言クラスがBeanである注釈
2.スキャンパッケージ、クラスロード、Bean作成
classのロード、beanの作成を管理する
スキャンパッケージは基本的に前のブログの内容で、あまり言わないで、Beanのインスタンス化を直接見ます.
実現構想は比較的明確で、大まかな流れは以下の通りである.Classコレクションを巡る 判断 beanと決定されると、インスタンス化 使用するたびにスキャンしないようにするため、このスキャンの結果は保存され、メモリに保存されます.
実際のロード手順は次のとおりです.
上記の実現は比較的簡単で、唯一注意しなければならないのは私たちが期待しているいくつかの注釈が含まれているかどうかを判断することであり、より優雅な書き方があるかどうか分からない.
次に注記のvalue属性が指定されている場合、beanNameは指定された値です. そうでなければ、class名によって、頭文字を小文字にすればいい 3.IoC依存注入
これも比較的簡単で、各beanの属性をスキャンして、
属性は値を割り当てて、下の2行のコードに注目すればいいです
4.クエリーbean&動的登録
クエリーのいくつかのインタフェースは比較的に簡単で、単純にMapからオブジェクトを取得します;登録とは、Mapにオブジェクトを挿入することです.
その他
ソースアドレス:https://github.com/liuyueyi/quick-mvc
関連ブログ:Javaパッケージパスの下classファイル をスキャンしてロード
個人ブログ:一灰の個人ブログ
公衆番号の詳細:
個人情報
前にjavaパケットのスキャンを実現し、スキャン後に自然にbeanのロードに達し、spring mvcの大きな特性IoC依存注入の実現を実現した.
ここでは,beanの負荷と依存注入の実現を以前に基づいて実現する.
デザイン
私たちが真似した車輪はspring mvcで、いくつかの複雑なシーンを簡略化して、ここでは注釈の形式だけを実現します
1.spring-mvcの使用姿勢に依存し、いくつかの注釈を定義する必要があります.
Service
,Component
,Repository
,Bean
,Autowired
@Autowired
2.インスタンス化bean
ClassによるBeanオブジェクトの作成
3.ロード依存
各Beanのプロパティをスキャンし、
Autowired.java
注記が含まれている場合はbeanで割り当てます.4.beanを取得するための様々な方法を提供する
最も一般的なのはbeanName、beanタイプによってBeanを取得します
5.動的登録beanの提供
たとえば、サードパーティのjarパッケージのクラスに依存して、サードパーティのクラスを変更できないため、動的登録でbeanをロードすることもできます.
インプリメンテーション
1.注記定義
これは比較的に簡単で、直接いくつかの関連する注釈を貼ります
いくつかの宣言クラスがBeanである注釈
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
String value() default "";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Bean
public @interface Component {
String value() default "";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Bean
public @interface Service {
String value() default "";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Bean
public @interface Repository {
String value() default "";
}
BeanFactory
,valueは事業者定義のbeanNameに対応@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
String value() default "";
}
2.スキャンパッケージ、クラスロード、Bean作成
classのロード、beanの作成を管理する
class
オブジェクトを定義します.スキャンパッケージは基本的に前のブログの内容で、あまり言わないで、Beanのインスタンス化を直接見ます.
実現構想は比較的明確で、大まかな流れは以下の通りである.
@Service
にBeanと定義された注釈がいくつかあるかどうか/**
* bean ,
* key bean name
* - ( value , bean name value ; , )
* - bean name
*
* bean name , value Map
*/
private Map> nameBeanMap;
/**
* class bean
*/
private Map clzBeanMap;
実際のロード手順は次のとおりです.
/**
* bean
*
* @return
*/
private Map> instanceBean() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
nameBeanMap = new ConcurrentHashMap<>();
clzBeanMap = new ConcurrentHashMap<>();
Annotation[] typeAnos;
String tmpBeanName;
Method tmpMethod;
Object tmpBean;
Map tmpClzMap;
for (Class clz : beanClasses) {
if (clz.isInterface()) {
continue;
}
//
typeAnos = clz.getAnnotations();
if (typeAnos.length == 0) {
continue;
}
for (Annotation ano : typeAnos) {
if (ano instanceof Bean || ano.annotationType().isAnnotationPresent(Bean.class)) { // bean
tmpMethod = ano.annotationType().getMethod("value", null);
if (tmpMethod != null) {
tmpBeanName = (String) tmpMethod.invoke(ano, null);
} else {
tmpBeanName = null;
}
if (StringUtils.isEmpty(tmpBeanName)) {
tmpBeanName = StrUtil.lowerFirstChar(clz.getSimpleName());
}
if (nameBeanMap.containsKey(tmpBeanName)) {
tmpClzMap = nameBeanMap.get(tmpBeanName);
} else {
tmpClzMap = new ConcurrentHashMap<>();
}
if (tmpClzMap.containsKey(clz)) {
throw new BeanAlreadyDefinedException("bean " + tmpBeanName + " class: " + clz.getName() + " has already defined!");
}
tmpBean = clz.newInstance();
tmpClzMap.put(clz, tmpBean);
clzBeanMap.put(clz, tmpBean);
nameBeanMap.put(tmpBeanName, tmpClzMap);
break;
}
}
}
return nameBeanMap;
}
上記の実現は比較的簡単で、唯一注意しなければならないのは私たちが期待しているいくつかの注釈が含まれているかどうかを判断することであり、より優雅な書き方があるかどうか分からない.
if(ano instanceof Bean || ano.annotationType().isAnnotationPresent(Bean.class)) {
// xxx
}
次に
BeanName
の生成ルールこれも比較的簡単で、各beanの属性をスキャンして、
@Autowired
注釈を持つものを持ち出して、それから対応するBeanを調べて、値を付与すればいいです/**
*
*/
private void ioc() throws IllegalAccessException {
Field[] fields;
String beanName;
Object bean;
for (Object obj : nameBeanMap.values()) {
fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(Autowired.class)) {
continue;
}
Autowired autowired = field.getAnnotation(Autowired.class);
beanName = StringUtils.isBlank(autowired.value()) ?
StrUtil.lowerFirstChar(field.getName()) : autowired.value();
bean = nameBeanMap.get(beanName);
if (bean == null) {
throw new BeanNotFoundException("bean: " + beanName + " not found! bean class: " + field.getClass().getName());
}
field.setAccessible(true);
field.set(obj, nameBeanMap.get(beanName));
}
}
}
属性は値を割り当てて、下の2行のコードに注目すればいいです
// ,
field.setAccessible(true);
field.set(obj, nameBeanMap.get(beanName));
4.クエリーbean&動的登録
クエリーのいくつかのインタフェースは比較的に簡単で、単純にMapからオブジェクトを取得します;登録とは、Mapにオブジェクトを挿入することです.
その他
ソースアドレス:https://github.com/liuyueyi/quick-mvc
関連ブログ:
個人ブログ:一灰の個人ブログ
公衆番号の詳細:
個人情報