简单的手写springIOC
基于XML配置文件写
- 创建储存bean的配置信息
/**
* 储存bean的配置信息
*
*/
public class BeanDefition implements Serializable{
/**
*
*/
private static final long serialVersionUID = 2662518218761590377L;
private String id;
private String pkgClass;
private Boolean lazy=false;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPkgClass() {
return pkgClass;
}
public void setPkgClass(String pkgClass) {
this.pkgClass = pkgClass;
}
public Boolean getLazy() {
return lazy;
}
public void setLazy(Boolean lazy) {
this.lazy = lazy;
}
public String toString() {
return "BeanDefition [id=" + id + ", pkgClass=" + pkgClass + ", lazy=" + lazy + "]";
}
}
- 新建文件夹,写配置文件spring-configs.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="data" class="java.util.Data" lazy="true"/>
<bean id="obj" class="java.lang.Object" lazy="false"/>
</beans>
- 写ClassPathXmlApplicationContext进行测试
public class ClassPathXmlApplicationContext {
/**
* 通过map存储bean对象的定义的配置信息
*/
private Map<String,BeanDefition> beanMap=new HashMap<>();
/**
* 通过此map存储bean的实例
*/
private Map<String,Object> instanceMap=new HashMap<>();
public ClassPathXmlApplicationContext(String file) throws Exception {
//1.读取文件
InputStream in=
getClass().getClassLoader().getResourceAsStream(file);
//2.解析文件封装数据
parse(in);
}
/**xml解析基于dom实现
* @throws Exception */
private void parse(InputStream in) throws Exception {
//1.创建解析器对象
DocumentBuilder builder=
DocumentBuilderFactory.newInstance().newDocumentBuilder();
//2.解析流对象
Document doc=builder.parse(in);
//3.处理document
processDocument(doc);
}
private void processDocument(Document doc) throws Exception {
//1.获取所有bean元素
NodeList list = doc.getElementsByTagName("bean");
//2.迭代bean元素,对其配置信息封装
for (int i = 0; i < list.getLength(); i++) {
Node node=list.item(i);
//一个node对应一个
BeanDefition bd=new BeanDefition();
NamedNodeMap nMap=node.getAttributes();
bd.setId(nMap.getNamedItem("id").getNodeValue());
bd.setPkgClass(nMap.getNamedItem("class").getNodeValue());
bd.setLazy(Boolean.valueOf(nMap.getNamedItem("lazy").getNodeValue()));
beanMap.put(bd.getId(), bd);
//基于配置信息判断是否延迟加载
if(!bd.getLazy()) {
Class<?> cls=Class.forName(bd.getPkgClass());
Object obj=newBeanInstance(cls);
instanceMap.put(bd.getId(), obj);
}
System.out.println(instanceMap);
}
}
//基于反射技术创建实例
private Object newBeanInstance(Class<?> cls) throws Exception {
//Class<?> cls=Class.forName(pkgClass);
Constructor<?> con=cls.getDeclaredConstructor();
con.setAccessible(true);
return con.newInstance();
}
@SuppressWarnings("unchecked")
public <T>T getBean(String key,Class<T> t) throws Exception{
//1.潘顿当前是否有bean实例
Object obj=instanceMap.get(key);
if(obj!=null)return (T)obj;
//2.实例中没有对象则创建对象,然后储存
obj=newBeanInstance(t);
instanceMap.put(key, obj);
return (T)obj;
}
public static void main(String[] args) throws Exception {
//1.初始化spring容器
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("spring-configs.xml");
//2.获取bean实例
Object obj = context.getBean("obj", Object.class);
Date date =context.getBean("date", Date.class);
System.out.println(obj);
System.out.println(date);
}
}
基于注解方式书写
- 创建几个注解
(1).延迟加载注解
```java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Lazy {
boolean value() default true;
}
(2). DI注入注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
(3).配置信息注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String value() default "";
}
(4).加载类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
String value() default "";
}
- 创建两个加载的类
@Service("sysLogService")
@Lazy(true)
public class SysLogSrevice {
public SysLogSrevice(){
System.out.println("SysLogSrevice()");
}
public void show() {
System.out.println("调用的值");
}
}
@Service("sysUserService")
@Lazy(false)
public class SysUserService {
@Autowired
private SysLogSrevice sysLogSrevice;
public SysUserService() {
System.out.println("SysUserService()");
}
public void show() {
sysLogSrevice.show();
}
}
- 创建配置文件的类
@ComponentScan("com.java.spring.service")
public class SpringConfig {
}
- 创建测试类
public class AnnotationConfigApplicationContext {
/**
* 通过map存储bean对象的定义的配置信息
*/
private Map<String,BeanDefition> beanMap=new HashMap<>();
/**
* 通过此map存储bean的实例
*/
private Map<String,Object> instanceMap=new HashMap<>();
public AnnotationConfigApplicationContext(Class<?> cls) throws Exception {
//1.读取配置配置类中指定的包名
ComponentScan cs= cls.getDeclaredAnnotation(ComponentScan.class);
String pkg=cs.value();
//2.扫描指定包中的类
String classPath=pkg.replace(".", "/");
URL url=cls.getClassLoader().getSystemResource(classPath);
File fileDir=new File(url.getPath());
File[] classFile=fileDir.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isFile()&&file.getName().endsWith(".class");
}
});
//3.封装文件信息
processClassFIles(pkg,classFile);
}
private void processClassFIles(String pkg,File[] classFile) throws Exception {
for (File f : classFile) {
String pkgClass=pkg+"."+f.getName().substring(0,f.getName().lastIndexOf("."));
Class<?> targetCls=Class.forName(pkgClass);
if(!targetCls.isAnnotationPresent(Service.class))
continue;
Service service=targetCls.getDeclaredAnnotation(Service.class);
BeanDefition bd=new BeanDefition();
bd.setId(service.value());
bd.setPkgClass(pkgClass);
Lazy lazy=targetCls.getDeclaredAnnotation(Lazy.class);
if(lazy!=null) {
bd.setLazy(lazy.value());
}
beanMap.put(bd.getId(), bd);
if(!bd.getLazy()) {
Object obj=newBeanInstance(targetCls);
instanceMap.put(bd.getId(), obj);
}
}
//System.out.println("map="+instanceMap);
}
private Object newBeanInstance(Class<?> targetCls) throws Exception {
Constructor<?> con= targetCls.getDeclaredConstructor();
con.setAccessible(true);
Object newInstance = con.newInstance();
Field[] fileds=targetCls.getDeclaredFields();
if(fileds.length!=0&&fileds!=null) {
for (Field field : fileds) {
if(field.isAnnotationPresent(Autowired.class)) {
Object shuxing = getBean(field.getName(),field.getType());
if (shuxing!=null) {
field.setAccessible(true);
field.set(newInstance, shuxing);
}
}
}
}
return newInstance;
}
public <T>T getBean(String key,Class<?> cls) throws Exception{
Object obj=instanceMap.get(key);
if(obj!=null) return (T)obj;
obj=newBeanInstance(cls);
instanceMap.put(key, obj);
return (T)obj;
}
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx=
new AnnotationConfigApplicationContext(SpringConfig.class);
// SysLogSrevice logSrevice=
// ctx.getBean("sysLogSrevice", SysLogSrevice.class);
// System.out.println("ls="+logSrevice);
SysUserService UserSrevice=
ctx.getBean("sysUserService", SysUserService.class);
System.out.println("ls="+UserSrevice);
UserSrevice.show();
}
}