文章目录
- 阶段2—封装bean定义信息到Map
- 1.代码框架图
- 2.代码实现
- 1.文件目录
- 2.新增注解Scope存储单例或多例信息Scope.java
- 3.修改MonsterService.java指定多例注解
- 4.新增bean定义对象存储bean定义信息BeanDefinition.java
- 5.修改pom.xml增加依赖
- 6.修改容器实现bean定义信息扫描SunSpringApplicationContext.java
- 7.结果展示
- 3.该阶段完成的任务
- 阶段3—初始化bean单例池&实现依赖注入
- 1.初始化bean单例池
- 1.代码框架图
- 2.代码实现
- 1.修改SunSpringApplicationContext.java增加两个方法
- 2.修改SunSpringApplicationContext.java在构造方法初始化单例池
- 3.启动类AppMain.java
- 4.结果
- 3.该阶段完成的任务
- 2.实现依赖注入
- 1.代码实现
- 1.增加注解Autowired用来表示自动装配
- 2.修改MonsterDao.java
- 3.修改MonsterService.java
- 4.修改SunSpringApplicationContext.java的createBean,添加依赖注入逻辑
- 5.启动类AppMain.java
- 6.结果
- 3.总结IOC
- 1.单例bean的创建和依赖注入
- 2.多例bean的特殊处理
阶段2—封装bean定义信息到Map
1.代码框架图
2.代码实现
1.文件目录
2.新增注解Scope存储单例或多例信息Scope.java
package com.sun.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
String value() default "";
}
3.修改MonsterService.java指定多例注解
package com.sun.spring.component;
import com.sun.spring.annotation.Component;
import com.sun.spring.annotation.Scope;
@Scope(value = "prototype")
@Component(value = "monsterService")
public class MonsterService {
}
4.新增bean定义对象存储bean定义信息BeanDefinition.java
package com.sun.spring.ioc;
public class BeanDefinition {
private String scope;
private Class clazz;
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
@Override
public String toString() {
return "BeanDefinition{" +
"scope='" + scope + '\'' +
", clazz=" + clazz +
'}';
}
}
5.修改pom.xml增加依赖
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
6.修改容器实现bean定义信息扫描SunSpringApplicationContext.java
package com.sun.spring.ioc;
import com.sun.spring.annotation.Component;
import com.sun.spring.annotation.ComponentScan;
import com.sun.spring.annotation.Scope;
import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SunSpringApplicationContext {
private Class configClass;
private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
public SunSpringApplicationContext(Class configClass) throws ClassNotFoundException {
this.beanDefinitionScan(configClass);
}
public void beanDefinitionScan(Class configClass) throws ClassNotFoundException {
this.configClass = configClass;
ComponentScan componentScan = (ComponentScan) this.configClass.getDeclaredAnnotation(ComponentScan.class);
String path = componentScan.value();
System.out.println("要扫描的包=" + path);
ClassLoader classLoader = SunSpringApplicationContext.class.getClassLoader();
path = path.replace(".", "/");
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
String absolutePath = f.getAbsolutePath();
if (absolutePath.endsWith(".class")) {
String className = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.indexOf("."));
String fullPath = path.replace("/", ".") + "." + className;
Class<?> aClass = classLoader.loadClass(fullPath);
if (aClass.isAnnotationPresent(Component.class)) {
System.out.println("这是一个Spring bean=" + aClass);
BeanDefinition beanDefinition = new BeanDefinition();
Scope scopeAnnotation = aClass.getDeclaredAnnotation(Scope.class);
String scope = scopeAnnotation == null || scopeAnnotation.value().equals("") ?
"singleton" : scopeAnnotation.value();
beanDefinition.setScope(scope);
beanDefinition.setClazz(aClass);
Component componentAnnotation = aClass.getDeclaredAnnotation(Component.class);
String beanName = componentAnnotation.value().equals("") ?
StringUtils.uncapitalize(className) : componentAnnotation.value();
beanDefinitionMap.put(beanName, beanDefinition);
} else {
System.out.println("这不是一个Spring bean=" + aClass);
}
}
}
System.out.println("遍历输出beanDefinitionMap");
for (Map.Entry<String, BeanDefinition> beanDefinitionMap : beanDefinitionMap.entrySet()) {
System.out.println(beanDefinitionMap.getKey() + " " + beanDefinitionMap.getValue());
}
}
}
public Object getBean(String name) {
return null;
}
}
7.结果展示
3.该阶段完成的任务
- 新增注解Scope来存储单例/多例信息
- 新增bean定义对象,存储bean定义信息Scope和Class对象
- 扫描所有组件的信息,将bean定义信息以beanName - bean定义对象的形式存储到Map中
阶段3—初始化bean单例池&实现依赖注入
1.初始化bean单例池
1.代码框架图
2.代码实现
1.修改SunSpringApplicationContext.java增加两个方法
private Object createBean(BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
return instance;
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public Object getBean(String name) {
if (beanDefinitionMap.containsKey(name)) {
BeanDefinition beanDefinition = beanDefinitionMap.get(name);
if ("singleton".equals(beanDefinition.getScope())) {
return singletonObjects.get(name);
} else {
return createBean(beanDefinition);
}
} else {
throw new NullPointerException("没有该bean");
}
}
2.修改SunSpringApplicationContext.java在构造方法初始化单例池
public SunSpringApplicationContext(Class configClass) throws ClassNotFoundException {
this.beanDefinitionScan(configClass);
Enumeration<String> keys = beanDefinitionMap.keys();
while (keys.hasMoreElements()) {
String beanName = keys.nextElement();
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanDefinition);
singletonObjects.put(beanName, bean);
}
}
System.out.println("singletonObjects: " + singletonObjects);
}
3.启动类AppMain.java
package com.sun.spring;
import com.sun.spring.ioc.SunSpringApplicationContext;
import com.sun.spring.ioc.SunSpringConfig;
public class AppMain {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
SunSpringApplicationContext ioc = new SunSpringApplicationContext(SunSpringConfig.class);
Object bean01 = ioc.getBean("monsterDao111");
Object bean02 = ioc.getBean("monsterDao111");
System.out.println("单例对象1:" + bean01);
System.out.println("单例对象2:" +bean02);
Object bean1 = ioc.getBean("monsterService");
Object bean2 = ioc.getBean("monsterService");
System.out.println("多例对象1:" + bean1);
System.out.println("多例对象1:" + bean2);
}
}
4.结果
3.该阶段完成的任务
- 新增createBean的方法,根据bean定义对象创建bean对象
- 新增初始化单例池,在封装完bean定义信息之后,扫描bean定义信息,如果是单例对象则创建bean对象放到单例池中
- 新增getBean方法,如果是单例的对象,则从单例池中查找,否则直接创建对象
2.实现依赖注入
1.代码实现
1.增加注解Autowired用来表示自动装配
package com.sun.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
2.修改MonsterDao.java
package com.sun.spring.component;
import com.sun.spring.annotation.Component;
@Component(value = "monsterDao")
public class MonsterDao {
public void hi() {
System.out.println("MonsterDao say hi!");
}
}
3.修改MonsterService.java
package com.sun.spring.component;
import com.sun.spring.annotation.Autowired;
import com.sun.spring.annotation.Component;
import com.sun.spring.annotation.Scope;
@Scope(value = "prototype")
@Component(value = "monsterService")
public class MonsterService {
@Autowired
private MonsterDao monsterDao;
public void m1() {
monsterDao.hi();
}
}
4.修改SunSpringApplicationContext.java的createBean,添加依赖注入逻辑
private Object createBean(BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
String name = field.getName();
Object bean = getBean(name);
field.setAccessible(true);
field.set(instance, bean);
}
}
return instance;
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
5.启动类AppMain.java
package com.sxs.spring;
import com.sxs.spring.aop.SmartAnimalable;
import com.sxs.spring.component.UserAction;
import com.sxs.spring.component.UserDao;
import com.sxs.spring.component.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppMain {
public static void main(String[] args) {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
UserAction action1 = ioc.getBean(UserAction.class);
UserAction action2 = ioc.getBean(UserAction.class);
System.out.println("action1=" + action1);
System.out.println("action2=" + action2);
UserService service = ioc.getBean(UserService.class);
System.out.println("service=" + service);
service.m1();
UserDao userDao = ioc.getBean(UserDao.class);
System.out.println("userDao=" + userDao);
SmartAnimalable bean = ioc.getBean(SmartAnimalable.class);
bean.getSum(1,2);
bean.getSub(2,1);
}
}
6.结果
3.总结IOC
1.单例bean的创建和依赖注入
- 获取Spring容器对象,读取配置文件,得到要扫描的包
- 扫描指定的包,将bean定义信息放到map中
- 初始化单例池,如果是单例的则直接反射创建bean对象并放到单例池中
- 依赖注入,扫描单例池中实例的所有字段,如果有自动装配注解则进行依赖注入
- 初始化bean对象
- getBean的时候从单例池中获取bean对象
- 销毁bean
2.多例bean的特殊处理
- getBean的时候反射创建bean对象,依赖注入,初始化bean,然后再得到bean对象
- 销毁bean