关于Spring框架的学习,通过底层的简单实现,能够更好的理解工厂对象的创建,以下代码是基于注解方式实现Spring工厂提供对象的方式。
1、代码实现的目录结构
2.目录结构的分层介绍
2.1自定义的注解cn.spring.annotation
@Component用来修饰需要创建对象的类
@ComponentScan用来修饰需要扫描包的注解类
2.2定义注解类cn.spring.config
2.3需要交由工厂创建对象的类 cn.spring.beans
2.4自定义工厂类 cn.spring.factory
package
cn.spring.factory;
import
cn.spring.annotation.
Component
;
import
cn.spring.annotation.
ComponentScan
;
import
java.io.File;
import
java.io.FileFilter;
import
java.lang.reflect.InvocationTargetException;
import
java.net.URL;
import
java.util.HashMap;
import
java.util.Map;
/**
* Created by lingkong on 2018/1/20.
*/
public class
AnnotationConfigApplicationContext {
private
Map
beanMap
=
new
HashMap();
public
AnnotationConfigApplicationContext(Class> cls)
throws
ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1.获取自定义类上的注解
//cls:自定义用来扫描注解的类的.class文件
//Component.class: 自定的注解,包含此注解的对象将会被创建对象
ComponentScan
annotation = cls.getAnnotation(
ComponentScan
.
class
);
//2.获取注解的值,该值为需要扫描的路径
String pkgName = annotation.value();
//3.获取的路径是以"."作为分隔符,需全部替换为"/"
String pkgPath= pkgName.replaceAll(
"
\\
."
,
"/"
);
//4.获取该路径的统一资源全路径
URL url = getClass().getClassLoader().getResource(pkgPath);
//5.获取绝对路径,并创建文件对象
File fileObj =
new
File(url.getPath());
//6.获取该文件下的所有文件,并过滤出后缀名是.class的文件
File[] files = fileObj.listFiles(
new
FileFilter() {
public boolean
accept(File pathname) {
boolean
flag = pathname.getName().endsWith(
".class"
);
if
(flag)
return true
;
return false
;
}
});
//7.遍历获得所有.class文件
for
(File file:files){
//8.截取文件的类名
String clsName = file.getName().substring(
0
, file.getName().lastIndexOf(
"."
));
//9.通过反射获取类对象(此处有ClassNotFoundException异常先抛出)
System.
out
.println(clsName);
Class> aClass = Class.
forName
(pkgName +
"."
+ clsName);
//10.该类是否含有指定的注解Component
boolean
flag = aClass.isAnnotationPresent(
Component
.
class
);
//11.如果含有指定注解,就继续操作,没有就结束本次循环,获取下一个类
if
(!flag)
continue
;
//12.为含有指定注解的类创建对象,通过其无参构造器
// (此处有NoSuchMethodExceptionIllegalAccessException, InvocationTargetException,
// InstantiationException异常,先抛出)
Object obj = aClass.getDeclaredConstructor().newInstance();
//13.获取指定注解上的值
String value = aClass.getAnnotation(
Component
.
class
).value();
//14.判断该值是否为空
if
(
""
.equals(value)){
//15.如果为空,将类名首字母小写,赋值给value
value = String.
valueOf
(clsName.charAt(
0
)).toLowerCase() + clsName.substring(
1
);
}
//15.将value赋值给key,和obj组成键值对存入beanMap集合
String key = value;
beanMap
.put(key,obj);
}
/**
}
* 通过key值返回一个对象
*
@param
key
*
@return
*/
public
Object getBean(String key){
return
beanMap
.get(key);
}
/**
* 重写的方法
*
@param
key
*
@param
cls
*
@param
*
@return
*/
public
<
T
>
T
getBean(String key,Class<
T
> cls){
return
(
T
)
beanMap
.get(key);
}
/**
* 清空集合,实现关闭工厂
*/
public void
close(){
beanMap
.clear();
beanMap
=
null
;
}
}
2.5代码测试
import cn.spring.beans.ObjectGenerator;
import cn.spring.config.AnnotationConfig;
import cn.spring.factory.AnnotationConfigApplicationContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
/**
* Created by lyang on 2018/1/20.
*/
public class TestFactory {
private AnnotationConfigApplicationContext ac;
@Before
public void init() throws Exception {
ac = new AnnotationConfigApplicationContext(AnnotationConfig.class);
}
@Test
public void Test1(){
ObjectGenerator og = (ObjectGenerator)ac.getBean("object");
System.out.println(og);
}
@After
public void destroy(){
ac.close();
System.out.println(ac);
}
}