一、前言
- 文章目录:Spring源码深度解析:文章目录
- 参考文档
- 诸葛老师课程:spring源码深度解析高级篇
- 《Spring源码深度解析》
- 如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正
二、手写模拟Spring
我们在学习Spring源码之前,我们先整体的了解一下Spring容器由哪些组成,主要是由于IOC和AOP构成。
然后自己先模拟手写一下Spring容器的整体架构,这样通过简单地demo让我们更加通俗的理解一个Spring容器主要做了哪些事情。方便为我们后面学习Spring源码。
1、Spring框架初始化结构
-
创建两个包名
-
创建启动类
添加“com.wts.spring.WtsApplicationContext”类,代码如下:/** * 启动类 */ public class WtsApplicationContext { }
-
创建一个业务类和测试类:
业务类
添加“com.wts.service.UserService”类,代码如下:public class UserService { }
测试类
添加“com.wts.service.Test”类,代码如下:public class Test { public static void main(String[] args) { } }
-
创建一个配置类
添加“com.wts.service.AppConfig”类,代码如下:/** * 配置类 */ public class AppConfig { }
-
创建一个
ComponentScan
扫描注解
添加“com.wts.spring.ComponentScan”类,代码如下:@Retention修饰注解,用来表示注解的生命周期; RetentionPolicy.RUNTIME 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在; 运行时也存在; 需要在运行时去动态获取注解信息
@Target:注解的作用目标; ElementType.TYPE:指定到接口、类、枚举、注解上/** * 扫描注解 */ @Retention(RetentionPolicy.RUNTIME) // @Retention修饰注解,用来表示注解的生命周期; RetentionPolicy.RUNTIME 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在; 运行时也存在; 需要在运行时去动态获取注解信息 @Target({ElementType.TYPE}) //@Target:注解的作用目标; ElementType.TYPE:指定到接口、类、枚举、注解上 public @interface ComponentScan { String value() default ""; }
-
创建一个
Componet
注解
添加“com.wts.spring.Component”类,代码如下:/** * 配置注解 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface Component { String value() default ""; }
-
配置类扫描service类
修改“com.wts.service.AppConfig”类,代码如下:/** * 配置类 */ @ComponentScan("com.wts.service") public class AppConfig { }
-
业务类添加
@Componet
注解
修改“com.wts.service.UserService”类,代码如下:@Component("userService") public class UserService { }
-
启动类添加
configClass
属性,并且创建一个获取Bean
方法
修改“com.wts.spring.WtsApplicationContext”类,代码如下:public class WtsApplicationContext { private Class configClass; public WtsApplicationContext(Class configClass) { this.configClass = configClass; } /** * 获取Bean * * @param beanName * @return */ public Object getBean(String beanName){ return null; } }
-
测试类进行测试
修改“com.wts.service.Test”类,代码如下:public class Test { public static void main(String[] args) { WtsApplicationContext applicationContext = new WtsApplicationContext(AppConfig.class); UserService userService = (UserService) applicationContext.getBean("userService"); } }
【结果】
从结果我们可以看到获取的bean为null,那是因为我们虽然配置了扫描注解和配置注解,但是我们没有实现这些注解,接下来让我们去实现扫描注解,使得注解生效。
2、Spring扫描(ComponentScan)底层实现
修改“com.wts.spring.WtsApplicationContext”类,代码如下:
public class WtsApplicationContext {
private Class configClass;
public WtsApplicationContext(Class configClass) {
this.configClass = configClass;
// 扫描
// 判断该类有没有ComponentScan注解
if (configClass.isAnnotationPresent(ComponentScan.class)) {
// 拿到ComponentScan注解
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
// 扫描路径 com.wts.service(这个只是包名,下面一步转化成路径名)
String path = componentScanAnnotation.value();
String path1 = path.replace(".", "/"); // com/wts/service(相对路径)
// 获取类加载器
ClassLoader classLoader = WtsApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path1);
System.out.println("URL:" + resource);
// 获取file对象 通过相对路径拿到正确的文件路径
File file = new File(resource.getFile());
System.out.println("file对象:" + file);
// 判断file是不是一个文件夹
if (file.isDirectory()) {
// 拿到当前文件夹的所有文件
File[] files = file.listFiles();
for (File f : files) {
// 拿到文件的绝对路径
String fileName = f.getAbsolutePath();
System.out.println("绝对路径:" + fileName);
if (fileName.endsWith(".class")) {
// com\wts\service\UserService
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
// 类名
className = className.replace("\\", ".");
System.out.println("类名:" + className);
try {
// Class对象
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
// Bean
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
}
public Object getBean(String beanName) {
return null;
}
}
【结果】
现在我们已经实现了@ComponentScan
注解的功能,获取到了bean
对象的类名和类路径。这一功能我们虽然获取到了这个bean
类的信息,但是我们getBean()
方法还是不能拿到该bean
的信息,这时候我们就想想应该怎么拿到@ComponentScan
注解获取到的信息呢,我们就想到等@ComponentScan
注解底层实现获取这些bean
信息的时候先把它缓存起来,然后需要这些信息的时候,我们再调用就好了,所以接下来我们就继续按照我们的思路继续实现。先定义一个bean
信息的封装类,然后缓存起来。
因为spring的对象有可能是单例模式的(默认都是单例的),也有可能是原型模式的,所以我们的bean
的封装类定义两个属性
type
:Class对象scope
:范围(简单说就是对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式。)
3、手写模拟BeanDefinition的生成
-
创建BeanDefinition
添加“com.wts.spring.BeanDefinition”类,代码如下:public class BeanDefinition { /** * Class对象 */ private Class type; /** * 范围(简单说就是对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式。) */ private String scope; public Class getType() { return type; } public void setType(Class type) { this.type = type; } public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } }
-
创建Scope注解
添加“com.wts.spring.Scope”类,代码如下:import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Scope { String value() default ""; }
-
启动类修改
修改“com.wts.spring.WtsApplicationContext”类,代码如下:public class WtsApplicationContext { private Class configClass; // beanDefinition内存 private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(); public WtsApplicationContext(Class configClass) { this.configClass = configClass; // 1、扫描 --> BeanDefinition --> beanDefinitionMap // 判断该类有没有ComponentScan注解 if (configClass.isAnnotationPresent(ComponentScan.class)) { // 拿到ComponentScan注解 ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class); // 扫描路径 com.wts.service(这个只是包名,下面一步转化成路径名) String path = componentScanAnnotation.value(); String path1 = path.replace(".", "/"); // com/wts/service(相对路径) // 获取类加载器 ClassLoader classLoader = WtsApplicationContext.class.getClassLoader(); URL resource = classLoader.getResource(path1); System.out.println("URL:" + resource); // 获取file对象 通过相对路径拿到正确的文件路径 File file = new File(resource.getFile()); System.out.println("file对象:" + file); // 判断file是不是一个文件夹 if (file.isDirectory()) { // 拿到当前文件夹的所有文件 File[] files = file.listFiles(); for (File f : files) { // 拿到文件的绝对路径 String fileName = f.getAbsolutePath(); System.out.println("绝对路径:" + fileName); if (fileName.endsWith(".class")) { // com\wts\service\UserService String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class")); // 类名 className = className.replace("\\", "."); System.out.println("类名:" + className); try { // Class对象 Class<?> clazz = classLoader.loadClass(className); if (clazz.isAnnotationPresent(Component.class)) { // 获取Component注解 Component component = clazz.getAnnotation(Component.class); // 拿到beanName String beanName = component.value(); // 如果Componnet注解没有定义beanName,默认类第一个首字母小写的beanName if (beanName.equals("")){ beanName = Introspector.decapitalize(clazz.getSimpleName()); } // 创建BeanDefinition对象 BeanDefinition beanDefinition = new BeanDefinition(); // BeanDefinition对象初始化类型字段 beanDefinition.setType(clazz); // 判断是否有Scope注解, 如果有Scope注解,拿到Scope的值放到BeanDefinition对象的scope属性上;没有默认是单例 if (clazz.isAnnotationPresent(Scope.class)) { Scope scopeAnnotation = clazz.getAnnotation(Scope.class); beanDefinition.setScope(scopeAnnotation.value()); } else { beanDefinition.setScope("singleton"); } beanDefinitionMap.put(beanName, beanDefinition); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } } } public Object getBean(String beanName) { return null; } }
【结果】
我们可以看到已经把获取到的bean
信息缓存起来了,下面就让我们实现如何获取bean
信息
4、手写模拟getBean()方法的底层实现
修改“com.wts.spring.WtsApplicationContext”类,代码如下:
public class WtsApplicationContext {
private Class configClass;
// beanDefinition内存
private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
// 单例池
private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
/**
* spring容器构造方法
*
* @param configClass
*/
public WtsApplicationContext(Class configClass) {
this.configClass = configClass;
// 1、扫描 --> BeanDefinition --> beanDefinitionMap
// 判断该类有没有ComponentScan注解
if (configClass.isAnnotationPresent(ComponentScan.class)) {
// 拿到ComponentScan注解
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
// 扫描路径 com.wts.service(这个只是包名,下面一步转化成路径名)
String path = componentScanAnnotation.value();
String path1 = path.replace(".", "/"); // com/wts/service(相对路径)
// 获取类加载器
ClassLoader classLoader = WtsApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path1);
System.out.println("URL:" + resource);
// 获取file对象 通过相对路径拿到正确的文件路径
File file = new File(resource.getFile());
System.out.println("file对象:" + file);
// 判断file是不是一个文件夹
if (file.isDirectory()) {
// 拿到当前文件夹的所有文件
File[] files = file.listFiles();
for (File f : files) {
// 拿到文件的绝对路径
String fileName = f.getAbsolutePath();
System.out.println("绝对路径:" + fileName);
if (fileName.endsWith(".class")) {
// com\wts\service\UserService
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
// 类名
className = className.replace("\\", ".");
System.out.println("类名:" + className);
try {
// Class对象
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
// 获取Component注解
Component component = clazz.getAnnotation(Component.class);
// 拿到beanName
String beanName = component.value();
// 如果Componnet注解没有定义beanName,默认类第一个首字母小写的beanName
if (beanName.equals("")){
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
// 创建BeanDefinition对象
BeanDefinition beanDefinition = new BeanDefinition();
// BeanDefinition对象初始化类型字段
beanDefinition.setType(clazz);
// 判断是否有Scope注解, 如果有Scope注解,拿到Scope的值放到BeanDefinition对象的scope属性上;没有默认是单例
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
System.out.println("beanDefinitionMap:" + beanDefinitionMap);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
// 2、实例化单例Bean
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}
/**
* 创建bean
*
* @param beanName
* @param beanDefinition
* @return
*/
private Object createBean(String beanName, BeanDefinition beanDefinition) {
return null;
}
/**
* 获取Bean
*
* @param beanName
* @return
*/
public Object getBean(String beanName) {
// 根据map获取BeanDefinition对象
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new NullPointerException();
} else {
String scope = beanDefinition.getScope();
if (scope.equals("singleton")) {
// 去单例池里面拿bean对象,如果没有就创建Bean对象,并放到单例池中
Object bean = singletonObjects.get(beanName);
if (bean == null) {
Object o = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, o);
}
return bean;
} else {
// 多例 直接每一次创建bean对象
return createBean(beanName, beanDefinition);
}
}
}
}
5、手写模拟Bean的创建流程
/**
* 创建bean
*
* @param beanName
* @param beanDefinition
* @return
*/
private Object createBean(String beanName, BeanDefinition beanDefinition) {
// 当前bean对应的类
Class clazz = beanDefinition.getType();
try {
// 通过类的无参构造方法生成一个实例对象
Object instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
测试
public class Test {
public static void main(String[] args) {
WtsApplicationContext applicationContext = new WtsApplicationContext(AppConfig.class);
// UserService userService = (UserService) applicationContext.getBean("userService");
System.out.println(applicationContext.getBean("userService"));
System.out.println(applicationContext.getBean("userService"));
System.out.println(applicationContext.getBean("userService"));
System.out.println(applicationContext.getBean("userService"));
}
}
【结果】
1、输出为同一个对象,是单例bean
2、将UserService变为多例对象,输出结果为4个不同对象
6、手写模拟依赖注入
在Spring容器中修改以下代码,这样我们在使用Component
注解的时候,默认给我们命名的类名为首字母小写的类
-
创建@Autowired注解
添加“com.wts.spring.Autowired”类,代码如下:@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Autowired { }
-
创建OrderService
添加“com.wts.service.OrderService”类,代码如下:@Component public class OrderService { }
-
UserService注入OrderService类
修改“com.wts.service.UserService”类,代码如下:@Component("userService") public class UserService { @Autowired private OrderService orderService; public void test(){ System.out.println(orderService); } }
-
测试
修改“com.wts.service.Test”类,代码如下:public class Test { public static void main(String[] args) { WtsApplicationContext applicationContext = new WtsApplicationContext(AppConfig.class); UserService userService = (UserService) applicationContext.getBean("userService"); userService.test(); } }
发现查出结果为null
-
修改Spring容器的创建Bean方法:在创建bean对象的时候,为实例对象设置Autowired对象标注的类
修改“com.wts.spring.WtsApplicationContext”类,代码如下:/** * 创建bean * * @param beanName * @param beanDefinition * @return */ private Object createBean(String beanName, BeanDefinition beanDefinition) { // 当前bean对应的类 Class clazz = beanDefinition.getType(); try { // 通过类的无参构造方法生成一个实例对象 Object instance = clazz.getConstructor().newInstance(); // 依赖注入 for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Autowired.class)) { // 反射类中的setAccessible是启用和禁用访问安全检查的开关, field.setAccessible(true); field.set(instance, getBean(field.getName())); } } return instance; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; }
【结果】
7、手写模拟Aware回调机制
- 创建BeanNameAware接口
添加“com.wts.spring.BeanNameAware”类,代码如下:public interface BeanNameAware { public void setBeanName(String beanName); }
- 修改Spring容器的createBean()方法
修改“com.wts.spring.WtsApplicationContext”类,代码如下:/** * 创建bean * * @param beanName * @param beanDefinition * @return */ private Object createBean(String beanName, BeanDefinition beanDefinition) { // 当前bean对应的类 Class clazz = beanDefinition.getType(); try { // 通过类的无参构造方法生成一个实例对象 Object instance = clazz.getConstructor().newInstance(); // 依赖注入 for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Autowired.class)) { // 反射类中的setAccessible是启用和禁用访问安全检查的开关, field.setAccessible(true); field.set(instance, getBean(field.getName())); } } // Aware回调 if (instance instanceof BeanNameAware){ ((BeanNameAware) instance).setBeanName(beanName); } return instance; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; }
- 修改UserService类
修改“com.wts.service.UserService”类,代码如下:@Component("userService") public class UserService implements BeanNameAware { @Autowired private OrderService orderService; private String beanName; public void test(){ System.out.println(orderService); } @Override public void setBeanName(String beanName) { this.beanName = beanName; } }
8、手写模拟Spring初始化机制
- 创建InitializingBean接口
添加“com.wts.spring.InitializingBean”类,代码如下:public interface InitializingBean { public void afterPropertiesSet(); }
- 修改spring容器的createBean()方法
修改“com.wts.spring.WtsApplicationContext”类,代码如下:/** * 创建bean * * @param beanName * @param beanDefinition * @return */ private Object createBean(String beanName, BeanDefinition beanDefinition) { // 当前bean对应的类 Class clazz = beanDefinition.getType(); try { // 通过类的无参构造方法生成一个实例对象 Object instance = clazz.getConstructor().newInstance(); // 依赖注入 for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Autowired.class)) { // 反射类中的setAccessible是启用和禁用访问安全检查的开关, field.setAccessible(true); field.set(instance, getBean(field.getName())); } } // Aware回调 if (instance instanceof BeanNameAware){ ((BeanNameAware) instance).setBeanName(beanName); } // 初始化 if (instance instanceof InitializingBean){ ((InitializingBean) instance).afterPropertiesSet(); } // BeanPostProcessor 初始化后 AOP return instance; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; }
- 修改UserService类
修改“com.wts.service.UserService”类,代码如下:@Component("userService") public class UserService implements BeanNameAware, InitializingBean { @Autowired private OrderService orderService; private String beanName; private String xxx; public void test(){ System.out.println(orderService); } @Override public void setBeanName(String beanName) { this.beanName = beanName; } @Override public void afterPropertiesSet() { //。。。。。。。。 System.out.println("初始化方法"); } }
9、手写模拟BeanPostProcessor机制
-
创建BeanPostProcessor接口
添加“com.wts.spring.BeanPostProcessor”类,代码如下:public interface BeanPostProcessor { public void postProcessBeforeInitialization(String beanName, Object bean); public void postProcessAfterInitialization(String beanName, Object bean); }
-
修改spring容器的createBean()方法
修改“com.wts.service.UserService”类,代码如下:/** * 创建bean * * @param beanName * @param beanDefinition * @return */ private Object createBean(String beanName, BeanDefinition beanDefinition) { // 当前bean对应的类 Class clazz = beanDefinition.getType(); try { // 通过类的无参构造方法生成一个实例对象 Object instance = clazz.getConstructor().newInstance(); // 依赖注入 for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Autowired.class)) { // 反射类中的setAccessible是启用和禁用访问安全检查的开关, field.setAccessible(true); field.set(instance, getBean(field.getName())); } } // Aware回调 if (instance instanceof BeanNameAware){ ((BeanNameAware) instance).setBeanName(beanName); } // 初始化前 for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { beanPostProcessor.postProcessBeforeInitialization(beanName, instance); } // 初始化 if (instance instanceof InitializingBean){ ((InitializingBean) instance).afterPropertiesSet(); } // 初始化后 for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { beanPostProcessor.postProcessAfterInitialization(beanName, instance); } // BeanPostProcessor 初始化后 AOP return instance; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; }
-
创建WtsBeanPostProcessor类
修改“com.wts.service.WtsBeanPostProcessor”类,代码如下:@Component public class WtsBeanPostProcessor implements BeanPostProcessor { @Override public void postProcessBeforeInitialization(String beanName, Object bean) { if (beanName.equals("userService")) { System.out.println("111111"); } } @Override public void postProcessAfterInitialization(String beanName, Object bean) { if (beanName.equals("userService")) { System.out.println("222222"); } } }
-
测试
修改“com.wts.service.Test”类,代码如下public class Test { public static void main(String[] args) { WtsApplicationContext applicationContext = new WtsApplicationContext(AppConfig.class); UserService userService = (UserService) applicationContext.getBean("userService"); userService.test(); } }
【结果】
10、手写模拟AOP机制
-
修改BeanPostProcessor
修改“com.wts.spring.BeanPostProcessor”类,代码如下:public interface BeanPostProcessor { public Object postProcessBeforeInitialization(String beanName, Object bean); public Object postProcessAfterInitialization(String beanName, Object bean); }
-
修改spring容器的createBean()方法
修改“com.wts.spring.WtsApplicationContext”类,代码如下:/** * 创建bean * * @param beanName * @param beanDefinition * @return */ private Object createBean(String beanName, BeanDefinition beanDefinition) { // 当前bean对应的类 Class clazz = beanDefinition.getType(); try { // 通过类的无参构造方法生成一个实例对象 Object instance = clazz.getConstructor().newInstance(); // 依赖注入 for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Autowired.class)) { // 反射类中的setAccessible是启用和禁用访问安全检查的开关, field.setAccessible(true); field.set(instance, getBean(field.getName())); } } // Aware回调 if (instance instanceof BeanNameAware){ ((BeanNameAware) instance).setBeanName(beanName); } // 初始化前 for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { instance = beanPostProcessor.postProcessBeforeInitialization(beanName, instance); } // 初始化 if (instance instanceof InitializingBean){ ((InitializingBean) instance).afterPropertiesSet(); } // 初始化后 for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { instance = beanPostProcessor.postProcessAfterInitialization(beanName, instance); } // BeanPostProcessor 初始化后 AOP return instance; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; }
-
创建UserInterface接口
添加“com.wts.service.UserInterface”类,代码如下:public interface UserInterface { public void test(); }
-
修改UserService类
修改“com.wts.service.UserService”类,代码如下:@Component("userService") public class UserService implements BeanNameAware, InitializingBean, UserInterface { @Autowired private OrderService orderService; private String beanName; private String xxx; @Override public void test(){ System.out.println(orderService); } @Override public void setBeanName(String beanName) { this.beanName = beanName; } @Override public void afterPropertiesSet() { //。。。。。。。。 System.out.println("初始化方法"); } }
-
修改WtsBeanPostProcessor类
修改“com.wts.service.WtsBeanPostProcessor”类,代码如下:@Component public class WtsBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(String beanName, Object bean) { if (beanName.equals("userService")) { System.out.println("111111"); } return bean; } @Override public Object postProcessAfterInitialization(String beanName, Object bean) { if (beanName.equals("userService")) { System.out.println("222222"); Object proxyInstance = Proxy.newProxyInstance(WtsBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("切面逻辑"); return method.invoke(bean, args); } }); return proxyInstance; } return bean; } }
-
测试:
修改“com.wts.service.Test”类,代码如下:public class Test { public static void main(String[] args) { WtsApplicationContext applicationContext = new WtsApplicationContext(AppConfig.class); UserService userService = (UserService) applicationContext.getBean("userService"); userService.test(); } }
【结果】:
修改测试方法
【结果】
三、手写模拟Bean的生命周期
1、创建Bean的生命周期
UserService---->推断构造---->普通对象----->依赖注入---->初始化前(@PostConstruct)----->初始化(InitializingBean)---->初始化后(AOP)---->代理对象-----> 放入Map单例池中---->Bean对象
2、创建一个modle: spring-hello
-
创建OrderService业务类
添加“com.wts.service.OrderService”类,代码如下:@Component public class OrderService { }
-
创建一个UserService 类
添加“com.wts.service.UserService ”类,代码如下:@Component public class UserService { @Autowired private OrderService orderService; public void test(){ System.out.println(orderService); } }
-
创建一个AppConfig配置类
添加“com.wts.AppConfig”类,代码如下:@ComponentScan("com.wts") public class AppConfig { }
-
创建测试类
添加“com.wts.Test”类,代码如下:public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = (UserService) applicationContext.getBean("userService"); userService.test(); }
测试:
3、具体实现
- 普通对象
在test的main方法里实例化UserService对象
UserService userService1 = new UserService();
- 依赖注入
判断当前属性是否有Autowired注解,给当前属性赋值
public class Test {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
/**
* 创建
* UserService---->推断构造---->普通对象----->依赖注入---->初始化前(@PostConstruct)
* ----->初始化(InitializingBean)---->初始化后(AOP)---->代理对象-----> 放入Map单例池中---->Bean对象
*/
UserService userService1 = new UserService();
// 依赖注入实现
// 获取对象的所有属性
for (Field field : userService1.getClass().getDeclaredFields()) {
// 判断当前属性是否有Autowired注解
if (field.isAnnotationPresent(Autowired.class)) {
// 给当前属性赋值
field.set(userService1, ??);
}
}
}
-
初始化前
创建一个User类
添加“com.wts.service.User”类,代码如下:public class User { }
修改UserService类中代码:admin属性不通过@Autowired注解注入,而是创建一个a()方法,并在方法上加上@PostConstruct注解
@Component public class UserService { @Autowired private OrderService orderService; // @Autowired private User admin; // new User(); @PostConstruct public void a(){ // mysql--->管理员的数据--->User对象---->this.admin } public void test(){ System.out.println(orderService); } }
test中的main方法简写初始化前如何实现
public class Test { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = (UserService) applicationContext.getBean("userService"); userService.test(); /** * 创建 * UserService---->推断构造---->普通对象----->依赖注入---->初始化前(@PostConstruct) * ----->初始化(InitializingBean)---->初始化后(AOP)---->代理对象-----> 放入Map单例池中---->Bean对象 */ UserService userService1 = new UserService(); // 依赖注入实现 // 获取对象的所有属性 // for (Field field : userService1.getClass().getDeclaredFields()) { // // 判断当前属性是否有Autowired注解 // if (field.isAnnotationPresent(Autowired.class)) { // // 给当前属性赋值 // field.set(userService1, ??); // } // } // 初始化前 // 获取当前对象的所有方法 for (Method method : userService1.getClass().getDeclaredMethods()) { // 判断当前方法是否有PostConstruct注解 if (method.isAnnotationPresent(PostConstruct.class)){ method.invoke(userService1, null); } } } }
-
初始化
UserService类实现spring自带的InitializingBean接口,并继承afterPropertiesSet()方法,并通过该方法对admin属性进行赋值@Component public class UserService implements InitializingBean { @Autowired private OrderService orderService; // @Autowired private User admin; // new User(); // @PostConstruct public void a(){ // mysql--->管理员的数据--->User对象---->this.admin } public void test(){ System.out.println(orderService); } @Override public void afterPropertiesSet() throws Exception { // mysql--->管理员的数据--->User对象---->this.admin } }
-
推断构造
spring先通过类型查找Bean(byType)–>类型没有再通过bean名字查找Bean(byName) 单例池Map<beanName, Bean对象>
1、创建OrderService类的名字为orderService@Component public class OrderService { // orderService }
2、创建OrderService类的名字分别为orderService1、orderService2
@ComponentScan("com.wts") public class AppConfig { @Bean public OrderService orderService1(){ return new OrderService(); } @Bean public OrderService orderService2(){ return new OrderService(); } }
测试
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { System.out.println(applicationContext.getBean("orderService")); System.out.println(applicationContext.getBean("orderService1")); System.out.println(applicationContext.getBean("orderService2")); }
-
AOP
UserService类:com.wts.service.UserService@Component public class UserService { @Autowired private OrderService orderService; public void test(){ System.out.println(orderService); } }
OrderService类:com.wts.service.OrderService
@Component public class OrderService { // orderService }
创建切面WtsAspect:com.wts.aspect.WtsAspect
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class WtsAspect { @Before("execution(public void com.wts.service.UserService.test())") public void wtsBefore(){ System.out.println("wtsBefore"); } }
打开AOP
@ComponentScan("com.wts") @EnableAspectJAutoProxy // 打开AOP public class AppConfig { }
UserServiceProxy对象---->UserService代理对象---->UserService代理对象.target=普通对象
UserService代理对象.test()---->
class UserServiceProxy extends UserService { UserService target; public void test(){ // @Before 增强逻辑 // target.test(); // 普通对象.test() } }
事务
开启事务package com.wts; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @ComponentScan("com.wts") @EnableTransactionManagement // 开启事务 public class AppConfig { @Bean public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(datasource()); } @Bean public PlatformTransactionManager transactionManager() { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(datasource()); return transactionManager; } @Bean public DataSource datasource(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&SSL=false"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; } }
UserService执行sql
@Component public class UserService { @Autowired private OrderService orderService; @Autowired private JdbcTemplate jdbcTemplate; @Transactional public void test(){ jdbcTemplate.execute("insert into t1 values (1, 1, 1, '1')"); throw new NullPointerException(); } }
事务管理器建立一个数据库连接conn ThreadLocal<Map<Datasource对象,数据库连接conn>>
加上@Configuration注解 Appconfig产生一个动态代理对象,JdbcTemplate的dasource对象和transactionManager的datasource对象是同一个,因为都是代理对象在执行datasource()方法,会去ThreadLocal判断是否有,有直接取UserServiceProxy对象---->UserService代理对象---->UserService代理对象.target=普通对象
UserService代理对象.test()---->
class UserServiceProxy extends UserService { UserService target; public void test(){ // 有没有@Transactional // 事务管理器建立一个数据库连接conn ThreadLocal<Map<Datasource对象,数据库连接conn>> // conn.autocommit = false // target.test(); // 普通对象.test() // connn.rollback() conn.commit() } }