手写spring准备工作:
新建一个maven工程:
架构
新建类:
package com.spring;
public class keweiqinApplicationContext {
private Class configClass;
public keweiqinApplicationContext(Class configClass) {
this.configClass = configClass;
}
//解析配置类
//ComponentScan注解---》扫描路径----》扫描
public Object getBean(String beanName){
return null;
}
}
注解
package com.spring;
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 ComponentScan {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";
}
package com.keweiqin;
import com.spring.ComponentScan;
@ComponentScan("com.keweiqin.service")
public class AppConfig {
}
大致情况:
在keweiqin包下新增一个Service包
里面两个类:UserService,xxxUtil
public class UserService {
}
public class XXXutil {
}
大致架构:
手写扫描逻辑(上)
public class keweiqinApplicationContext {
private Class configClass;
public keweiqinApplicationContext(Class configClass) {
this.configClass = configClass;
//解析配置类
//ComponentScan注解---》扫描路径----》扫描
//拿到这个配置类上的ComponentScan注解
ComponentScan componentScanAnnotation =
(ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//拿到扫描路径
String path = componentScanAnnotation.value();//path:com.keweiqin.service
path=path.replace(".","/");
//拿到类加载器
ClassLoader classLoader = keweiqinApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();//D:\project\spring-study\springByWrite\target\classes\com\keweiqin\service\UserService.class
if (fileName.endsWith(".class")) {
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("\\", ".");
try {
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
//表示当前类是一个bean
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
public Object getBean(String beanName){
return null;
}
}
手写扫描逻辑下以及BeanDefinition对象
新增注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() ;
}
userService
@Component("userService")
@Scope("prototype")
public class UserService {
}
新增BeanDefinition类
public class BeanDefinition {
//类
private Class clazz;
//什么类型的bean
private String scope;
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}
充实keweiqinApplicationContext
public class keweiqinApplicationContext {
private Class configClass;
//模拟单例池
private ConcurrentHashMap<String,Object> singletonObjects=new ConcurrentHashMap<>();
//存放beanDefinition的一个集合
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>();
public keweiqinApplicationContext(Class configClass) {
this.configClass = configClass;
//解析配置类
//ComponentScan注解---》扫描路径----》扫描---->BeandeFinition-->BeanDefinitionMap
//拿到这个配置类上的ComponentScan注解
scan(configClass);
for (Map.Entry<String,BeanDefinition> entry:beanDefinitionMap.entrySet()){
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")){
Object bean = createBean(beanDefinition);
singletonObjects.put(beanName,bean);
}
}
}
public Object createBean(BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;}
private void scan(Class configClass) {
ComponentScan componentScanAnnotation =
(ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//拿到扫描路径
String path = componentScanAnnotation.value();//path:com.keweiqin.service
path=path.replace(".","/");
//拿到类加载器
ClassLoader classLoader = keweiqinApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();//D:\project\spring-study\springByWrite\target\classes\com\keweiqin\service\UserService.class
if (fileName.endsWith(".class")) {
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("\\", ".");
try {
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
//表示当前类是一个bean
//解析类---->BeanDefinition
Component componentAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName = componentAnnotation.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
if (clazz.isAnnotationPresent(Scope.class)){
Scope scopeAnnotation = clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
}else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
public Object getBean(String beanName){
if (beanDefinitionMap.containsKey(beanName)){
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")){
Object o = singletonObjects.get(beanName);
return o;
}else {
//创建Bean对象
Object bean = createBean(beanDefinition);
return bean;
}
}else {
//不存在对应的Bean
throw new NullPointerException();
}
}
}
架构
测试!!!
public class Test {
public static void main(String[] args) {
keweiqinApplicationContext applicationContext = new keweiqinApplicationContext(AppConfig.class);
System.out.println(applicationContext.getBean("userService"));
System.out.println(applicationContext.getBean("userService"));
System.out.println(applicationContext.getBean("userService"));
}
}
修改
@Component("userService")
public class UserService {
}
测试输出:
手写spring之依赖注入模拟实现
新增类OrderService
@Component("orderService")
public class OrderService {
}
修改userService
@Component("userService")
public class UserService {
@Autowired
private OrderService orderService;
public void test(){
System.out.println(orderService);
}
}
新增注解Autowired
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD})
public @interface Autowired {
}
主类:
public class Test {
public static void main(String[] args) {
keweiqinApplicationContext applicationContext = new keweiqinApplicationContext(AppConfig.class);
UserService userService = (UserService)applicationContext.getBean("userService");
userService.test();
}
}
测试发现输出是null
在keweiqinApplicationContext增加以下内容
public Object createBean(BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
//依赖注入
for (Field declaredField:clazz.getDeclaredFields()){
if (declaredField.isAnnotationPresent(Autowired.class)){
Object bean = getBean(declaredField.getName());
declaredField.setAccessible(true);
declaredField.set(instance,bean);
}
}
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 keweiqinApplicationContext {
private Class configClass;
//模拟单例池
private ConcurrentHashMap<String,Object> singletonObjects=new ConcurrentHashMap<>();
//存放beanDefinition的一个集合
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>();
public keweiqinApplicationContext(Class configClass) {
this.configClass = configClass;
//解析配置类
//ComponentScan注解---》扫描路径----》扫描---->BeandeFinition-->BeanDefinitionMap
//拿到这个配置类上的ComponentScan注解
scan(configClass);
for (Map.Entry<String,BeanDefinition> entry:beanDefinitionMap.entrySet()){
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")){
Object bean = createBean(beanDefinition);
singletonObjects.put(beanName,bean);
}
}
}
public Object createBean(BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
//依赖注入
for (Field declaredField:clazz.getDeclaredFields()){
if (declaredField.isAnnotationPresent(Autowired.class)){
Object bean = getBean(declaredField.getName());
declaredField.setAccessible(true);
declaredField.set(instance,bean);
}
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;}
private void scan(Class configClass) {
ComponentScan componentScanAnnotation =
(ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//拿到扫描路径
String path = componentScanAnnotation.value();//path:com.keweiqin.service
path=path.replace(".","/");
//拿到类加载器
ClassLoader classLoader = keweiqinApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();//D:\project\spring-study\springByWrite\target\classes\com\keweiqin\service\UserService.class
if (fileName.endsWith(".class")) {
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("\\", ".");
try {
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
//表示当前类是一个bean
//解析类---->BeanDefinition
Component componentAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName = componentAnnotation.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
if (clazz.isAnnotationPresent(Scope.class)){
Scope scopeAnnotation = clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
}else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
public Object getBean(String beanName){
if (beanDefinitionMap.containsKey(beanName)){
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")){
Object o = singletonObjects.get(beanName);
return o;
}else {
//创建Bean对象
Object bean = createBean(beanDefinition);
return bean;
}
}else {
//不存在对应的Bean
throw new NullPointerException();
}
}
}
输出:
手写spring之set方法依赖注入模拟实现
新建BeanNameAware
public interface BeanNameAware {
void setBeanName(String name);
}
UserService
@Component("userService")
public class UserService implements BeanNameAware {
@Autowired
private OrderService orderService;
private String beanName;
public void test(){
System.out.println(orderService);
System.out.println(beanName);
}
@Override
public void setBeanName(String name) {
beanName=name;
}
}
修改createBean方法
public Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
//依赖注入
for (Field declaredField:clazz.getDeclaredFields()){
if (declaredField.isAnnotationPresent(Autowired.class)){
Object bean = getBean(declaredField.getName());
declaredField.setAccessible(true);
declaredField.set(instance,bean);
}
}
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;}
getBean
架构:
手写Spring之初始化机制模拟实现
新增接口
public interface InitalizingBean {
void afterPropertiesSet() throws Exception;
}
修改UserService
@Component("userService")
public class UserService implements InitalizingBean {
@Autowired
private OrderService orderService;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化");
}
public void test(){
System.out.println(orderService);
}
}
新加代码
输出:
手写Spring之BeanPostProcessor模拟实现
接口
public interface BeanPostProcessor {
Object postProcessBeforeInitialization (Object bean,String beanName);
Object postProcessAfterInitialization (Object bean,String beanName);
}
userService
package com.keweiqin.service;
import com.spring.*;
@Component("userService")
public class UserService implements InitalizingBean {
@Autowired
private OrderService orderService;
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化");
}
public void test(){
System.out.println(orderService);
System.out.println(name);
}
}
BeanPostProcessor
@Component
public class kwqBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("初始化前");
if (beanName.equals("userService")){
((UserService)bean).setName("kwq好帅");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("初始化后");
return bean;
}
}
修改keweiqinApplicationContext
增加代码
输出:
架构图
手写Spring之AOP模拟实现
新增接口
public interface UserService {
public void test();
}
@Component("userService")
public class UserServiceImpl implements UserService {
@Autowired
private OrderService orderService;
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void test(){
System.out.println(orderService);
System.out.println(name);
}
}
在初始化后方法中,生成代理对象
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("初始化后");
if (beanName.equals("userService")){
Object proxyInstance = Proxy.newProxyInstance(kwqBeanPostProcessor.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;
}
}
输出
整体代码
package com.spring;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class keweiqinApplicationContext {
private Class configClass;
//模拟单例池
private ConcurrentHashMap<String,Object> singletonObjects=new ConcurrentHashMap<>();
//存放beanDefinition的一个集合
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>();
private List<BeanPostProcessor> beanPostProcessorList=new ArrayList<>();
public keweiqinApplicationContext(Class configClass) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
this.configClass = configClass;
//解析配置类
//ComponentScan注解---》扫描路径----》扫描---->BeandeFinition-->BeanDefinitionMap
//拿到这个配置类上的ComponentScan注解
scan(configClass);
for (Map.Entry<String,BeanDefinition> entry:beanDefinitionMap.entrySet()){
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")){
Object bean = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,bean);
}
}
}
public Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
//依赖注入
for (Field declaredField:clazz.getDeclaredFields()){
if (declaredField.isAnnotationPresent(Autowired.class)){
Object bean = getBean(declaredField.getName());
declaredField.setAccessible(true);
declaredField.set(instance,bean);
}
}
//Aware回调
if (instance instanceof BeanNameAware){
((BeanNameAware)instance).setBeanName(beanName);
}
//初始化前
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
//初始化
if (instance instanceof InitalizingBean){
try {
((InitalizingBean)instance).afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
}
//初始化后
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, 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;}
private void scan(Class configClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
ComponentScan componentScanAnnotation =
(ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//拿到扫描路径
String path = componentScanAnnotation.value();//path:com.keweiqin.service
path=path.replace(".","/");
//拿到类加载器
ClassLoader classLoader = keweiqinApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();//D:\project\spring-study\springByWrite\target\classes\com\keweiqin\service\UserService.class
if (fileName.endsWith(".class")) {
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("\\", ".");
try {
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
//表示当前类是一个bean
//解析类---->BeanDefinition
//表示clazz是否实现了BeanPostProcessor接口
if (BeanPostProcessor.class.isAssignableFrom(clazz)){
BeanPostProcessor instance = (BeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
beanPostProcessorList.add(instance);
}
Component componentAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName = componentAnnotation.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
if (clazz.isAnnotationPresent(Scope.class)){
Scope scopeAnnotation = clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
}else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
public Object getBean(String beanName){
if (beanDefinitionMap.containsKey(beanName)){
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")){
Object o = singletonObjects.get(beanName);
return o;
}else {
//创建Bean对象
Object bean = createBean(beanName,beanDefinition);
return bean;
}
}else {
//不存在对应的Bean
throw new NullPointerException();
}
}
}