文章目录
阶段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