一.创建maven项目
二.创建对应的文件夹,分别是spring和nickel
说明:spring文件夹用于存放spring相关的文件,nickel用于存放相应的配置文件和相关被spring加载的bean对象。
三.创建对对应的文件
3.1创建CommponentScan注解文件
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:21
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CommponentScan {
String value() default "";
}
说明:该注解用于配置文件类上,用于spring应该扫描路径
3.2创建NickelAppConfig类
package com.spring;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:55
*/
@CommponentScan("com.nickel.service")
public class NickelAppConfig {
}
说明:该类用于配置Spring应该扫描的文件夹,通过CommponentScan注解里面的值来确定扫描的路径
3.3创建NickelAnnotationConfigApplicationContext
package com.spring;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
}
public Object getBean(String beanName){
return null;
}
}
说明:该类是spring加载容器,当spring加载时候,会加载该类,通过会加载所有Commponent注解的类,同时判断是单例加载还是多例加载,还有执行初始化相关的方法
3.4创建Commponent注解
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:21
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Commponent {
String value() default "";
}
说明:注解用于扫描的类上,用于管理该类是否被spring进行管理,value值用于存放在spring加载的key值
3.5创建Scope注解
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:36
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "";
}
说明:Scope注解用于类上,用于说明改类是单例bean,还是多实例bean,当没有Scope注解和Scope的value值为singleton为单实例bean,当值为prototype为多实例bean
3.6创建UserService类
package com.nickel.service;
import com.spring.Commponent;
import com.spring.Scope;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:43
*/
@Commponent("userService")
@Scope("singleton")
public class UserService {
public void test(){
System.out.println("test");
}
}
说明:改类有Commponent注解,表示会被spring加载,Scope的value值为singleton表示该类会被spring加载
3.7创建OrderService类
package com.nickel.service;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:44
*/
public class OrderService {
}
说明:该类没有Commponent注解,表示在spring加载的时候不会加载该类
四.Spring扫描的实现
4.1 在Test类中写对应的测试方法
package com.nickel;
import com.nickel.service.UserService;
import com.spring.NickelAnnotationConfigApplicationContext;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:16
*/
public class Test {
public static void main(String[] args) {
NickelAnnotationConfigApplicationContext context=new NickelAnnotationConfigApplicationContext(NickelAppConfig.class);
UserService userService = (UserService)context.getBean("userService");
userService.test();
}
}
说明:该类目前未实现加载bean的方法,所以执行该方法会报错,实现后续的方法将会加载。
4.2 NickelAnnotationConfigApplicationContext获取扫描的路径
package com.spring;
import java.lang.annotation.Annotation;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan)scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
System.out.println(path);
}
}
public Object getBean(String beanName){
return null;
}
}
说明:获取扫描配置文件中,CommponentScan注解的value值,获取spring项目的扫描路径
4.3创建对象BeanDefinition
package com.spring;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 9:42
*/
public class BeanDefinition {
private Class type;
private String scope;
private Boolean isLazy;
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;
}
public Boolean getLazy() {
return isLazy;
}
public void setLazy(Boolean lazy) {
isLazy = lazy;
}
}
说明:该类用于存储被Conponent注解标识的类。
4.3 通过SpringLoader来加载该类
package com.spring;
import java.lang.annotation.Annotation;
import java.net.URL;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan)scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
System.out.println(path);
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
}
}
public Object getBean(String beanName){
return null;
}
}
说明:由于springLoader是通过相对路径来加载文件的,相对路径的文件路径为/./…这种形式,所以在加载的时候‘.’路径修改为‘/’路径。
4.4 判断该类是否有Component注解和Scope注解来走不同的逻辑
package com.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.net.FileNameMap;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan)scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getPath());
for (File listFile : file.listFiles()) {
String absolutePath = listFile.getAbsolutePath();
absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
System.out.println(absolutePath);
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Commponent.class)) {
//判断该类是单例加载还是多例加载,没有Scope注解表示多例
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
String value = annotation.value();
if(value.equals("singleton")){
//单例
}else{
//多例
}
}else{
//单例
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
public Object getBean(String beanName){
return null;
}
}
说明:这里获取所有具有Commponent注解的类,这个类将会被spring加载,同时具有Scope注解值value为singleton将会被加载一次,其他的将会被加载多次。
4.4 提取扫描方法,创建beanDefinition对象,并把对象存放在beanDefinitionMap
package com.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.net.FileNameMap;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
scan(scanConfig);
}
public Object getBean(String beanName){
return null;
}
private void scan(Class scanConfig) {
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getPath());
for (File listFile : file.listFiles()) {
String absolutePath = listFile.getAbsolutePath();
absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
System.out.println(absolutePath);
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Commponent.class)) {
//获取beanName
Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
String beanName=commponentAnnotation.value();
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setType(aClass);
//判断该类是单例加载还是多例加载,没有Scope注解表示多例
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
String value = annotation.value();
beanDefinition.setScope(value);
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
4.5 创建bean方法,同时创建一个singletonObjects对象用于存所有单实例bean
package com.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
private Map<String,Object> singletonObjects=new HashMap<>();
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
scan(scanConfig);
//创建bean
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName=entry.getKey();
BeanDefinition beanDefinition= entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
}
}
public Object getBean(String beanName){
return null;
}
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz=beanDefinition.getType();
Object instance=null;
try {
instance = clazz.getConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
private void scan(Class scanConfig) {
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getPath());
for (File listFile : file.listFiles()) {
String absolutePath = listFile.getAbsolutePath();
absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
System.out.println(absolutePath);
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Commponent.class)) {
//获取beanName
Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
String beanName=commponentAnnotation.value();
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setType(aClass);
//判断该类是单例加载还是多例加载,没有Scope注解表示多例
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
String value = annotation.value();
beanDefinition.setScope(value);
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
4.6getBean方法修改
package com.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
private Map<String,Object> singletonObjects=new HashMap<>();
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
scan(scanConfig);
//创建bean
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName=entry.getKey();
BeanDefinition beanDefinition= entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
}
}
public Object getBean(String beanName){
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition.getScope().equals("singleton")){
Object singletonBean=singletonObjects.get(beanName);
if(singletonBean==null){
singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
return singletonBean;
}else{
return createBean(beanName,beanDefinition);
}
}
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz=beanDefinition.getType();
Object instance=null;
try {
instance = clazz.getConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
private void scan(Class scanConfig) {
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getPath());
for (File listFile : file.listFiles()) {
String absolutePath = listFile.getAbsolutePath();
absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Commponent.class)) {
//获取beanName
Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
String beanName=commponentAnnotation.value();
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setType(aClass);
//判断该类是单例加载还是多例加载,没有Scope注解表示多例
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
String value = annotation.value();
beanDefinition.setScope(value);
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
4.Test类修改,测试方法有效性
package com.nickel;
import com.spring.NickelAnnotationConfigApplicationContext;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:16
*/
public class Test {
public static void main(String[] args) {
NickelAnnotationConfigApplicationContext context=new NickelAnnotationConfigApplicationContext(NickelAppConfig.class);
System.out.println(context.getBean("userService"));
System.out.println(context.getBean("userService"));
}
}
五.Spring实现初始化,初始化前、初始化后的方法
5.1初始化前方法实现
由于spring实现初始化的方法是实现接口InitializingBean,同时实现接口里面afterPropertiesSet方法
1.创建InitializingBean接口,在接口中添加afterPropertiesSet方法
package com.spring;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 15:03
*/
public interface InitializingBean {
void afterPropertiesSet();
}
2.在创建bean的时候,判断方法是否实现InitializingBean接口,实现接口转化后实现初始化方法
package com.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
private Map<String,Object> singletonObjects=new HashMap<>();
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
scan(scanConfig);
//创建bean
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName=entry.getKey();
BeanDefinition beanDefinition= entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
}
}
public Object getBean(String beanName){
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition.getScope().equals("singleton")){
Object singletonBean=singletonObjects.get(beanName);
if(singletonBean==null){
singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
return singletonBean;
}else{
return createBean(beanName,beanDefinition);
}
}
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz=beanDefinition.getType();
Object instance=null;
try {
instance = clazz.getConstructor().newInstance();
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
private void scan(Class scanConfig) {
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getPath());
for (File listFile : file.listFiles()) {
String absolutePath = listFile.getAbsolutePath();
absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Commponent.class)) {
//获取beanName
Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
String beanName=commponentAnnotation.value();
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setType(aClass);
//判断该类是单例加载还是多例加载,没有Scope注解表示多例
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
String value = annotation.value();
beanDefinition.setScope(value);
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
3.Test测试类测试初始化的方法
package com.nickel;
import com.nickel.service.UserService;
import com.spring.NickelAnnotationConfigApplicationContext;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:16
*/
public class Test {
public static void main(String[] args) {
NickelAnnotationConfigApplicationContext context=new NickelAnnotationConfigApplicationContext(NickelAppConfig.class);
// System.out.println(context.getBean("userService"));
// System.out.println(context.getBean("userService"));
UserService userService = (UserService)context.getBean("userService");
userService.test();
}
}
5.2实现初始化前的方法
1.创建BeanPostProcess接口,在接口定义两个方法postProcessBeforeInitialization和postProcessAfterInitialization
package com.spring;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 15:44
*/
public interface BeanPostProcess {
default Object postProcessBeforeInitialization(Object bean, String beanName){
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName){
return bean;
}
}
2.定义一个方法NickelBeanPostProcess实现BeanPostProcess方法
package com.nickel.service;
import com.spring.BeanPostProcess;
import com.spring.Commponent;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 15:50
*/
@Commponent
public class NickelBeanPostProcss implements BeanPostProcess {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return BeanPostProcess.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if(beanName.equals("userService")){
System.out.println("userService初始化后");
}
return BeanPostProcess.super.postProcessAfterInitialization(bean, beanName);
}
}
说明:由于该方法要被spring进行管理,那么必须要在改类上面添加Commponent注解,这样类才会被加载
3.改造扫描方法,使得BeanPostProcess能够被加载,创建beanPostProcessList存放所有的BeanPostProcess方法
package com.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
private Map<String,Object> singletonObjects=new HashMap<>();
private List<BeanPostProcess> beanPostProcessList=new ArrayList<>();
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
scan(scanConfig);
//创建bean
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName=entry.getKey();
BeanDefinition beanDefinition= entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
}
}
public Object getBean(String beanName){
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition.getScope().equals("singleton")){
Object singletonBean=singletonObjects.get(beanName);
if(singletonBean==null){
singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
return singletonBean;
}else{
return createBean(beanName,beanDefinition);
}
}
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz=beanDefinition.getType();
Object instance=null;
try {
instance = clazz.getConstructor().newInstance();
for (BeanPostProcess beanPostProcess : beanPostProcessList) {
instance=beanPostProcess.postProcessBeforeInitialization(instance,beanName);
}
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
for (BeanPostProcess beanPostProcess : beanPostProcessList) {
instance=beanPostProcess.postProcessAfterInitialization(instance,beanName);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
private void scan(Class scanConfig) {
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getPath());
for (File listFile : file.listFiles()) {
String absolutePath = listFile.getAbsolutePath();
absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Commponent.class)) {
//判断是否实现BeanPostProcess方法
if (BeanPostProcess.class.isAssignableFrom(aClass)) {
BeanPostProcess beanPostProcess = (BeanPostProcess) aClass.getConstructor().newInstance();
beanPostProcessList.add(beanPostProcess);
}else{
//获取beanName
Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
String beanName=commponentAnnotation.value();
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setType(aClass);
//判断该类是单例加载还是多例加载,没有Scope注解表示多例
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
String value = annotation.value();
beanDefinition.setScope(value);
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
}
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
4.NickelBeanPostProcessor里面实现切面逻辑
4.1创建UserInterface接口
package com.nickel.service;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 16:45
*/
public interface UserInterface {
public void test();
}
4.2在UserService中实现接口
package com.nickel.service;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:43
*/
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface {
public void test(){
System.out.println("test");
}
@Override
public void afterPropertiesSet() {
System.out.println("初始化");
}
}
4.3在代理中配置相关切面的逻辑
package com.nickel.service;
import com.spring.BeanPostProcess;
import com.spring.Commponent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 15:50
*/
@Commponent
public class NickelBeanPostProcss implements BeanPostProcess {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if(beanName.equals("userService")){
//使用jdk动态代理
Object proxyInstance = Proxy.newProxyInstance(NickelBeanPostProcss.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;
}
}
4.4在测试类中进行测试
package com.nickel;
import com.nickel.service.UserInterface;
import com.nickel.service.UserService;
import com.spring.NickelAnnotationConfigApplicationContext;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:16
*/
public class Test {
public static void main(String[] args) {
NickelAnnotationConfigApplicationContext context=new NickelAnnotationConfigApplicationContext(NickelAppConfig.class);
// System.out.println(context.getBean("userService"));
// System.out.println(context.getBean("userService"));
UserInterface userService = (UserInterface)context.getBean("userService");
userService.test();
}
}
说明:由于代理的对象是接口,所以此时返回的对象是接口对象,这是需要转化为接口。
五.Spring实现Autowired自动注入
5.1创建自动注入对象
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:21
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}
5.2在UserService创建注入对象
package com.nickel.service;
import com.spring.Autowired;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:43
*/
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface {
@Autowired
private OrderService orderService;
public void test(){
System.out.println("test");
}
@Override
public void afterPropertiesSet() {
System.out.println("初始化");
System.out.println(orderService);
}
}
5.3在spring加载的时候,获取autowire注解
package com.spring;
import java.beans.Introspector;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
private Map<String,Object> singletonObjects=new HashMap<>();
private List<BeanPostProcess> beanPostProcessList=new ArrayList<>();
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
scan(scanConfig);
//创建bean
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName=entry.getKey();
BeanDefinition beanDefinition= entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
}
}
public Object getBean(String beanName){
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition.getScope().equals("singleton")){
Object singletonBean=singletonObjects.get(beanName);
if(singletonBean==null){
singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
return singletonBean;
}else{
return createBean(beanName,beanDefinition);
}
}
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz=beanDefinition.getType();
Object instance=null;
try {
instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
//获取方法中类型的对象
Object object= Introspector.decapitalize(field.getType().getSimpleName());
field.set(instance,getBean(object.toString()));
}
}
for (BeanPostProcess beanPostProcess : beanPostProcessList) {
instance=beanPostProcess.postProcessBeforeInitialization(instance,beanName);
}
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
for (BeanPostProcess beanPostProcess : beanPostProcessList) {
instance=beanPostProcess.postProcessAfterInitialization(instance,beanName);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
private void scan(Class scanConfig) {
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getPath());
for (File listFile : file.listFiles()) {
String absolutePath = listFile.getAbsolutePath();
absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Commponent.class)) {
//判断是否实现BeanPostProcess方法
if (BeanPostProcess.class.isAssignableFrom(aClass)) {
BeanPostProcess beanPostProcess = (BeanPostProcess) aClass.getConstructor().newInstance();
beanPostProcessList.add(beanPostProcess);
}else{
//获取beanName
Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
String beanName=commponentAnnotation.value();
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setType(aClass);
//判断该类是单例加载还是多例加载,没有Scope注解表示多例
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
String value = annotation.value();
beanDefinition.setScope(value);
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
}
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
六.Spring实现NickelValue注解上面的value直接赋值给属性
1.创建NickelValue注解对象
package com.nickel.service;
import com.spring.Autowired;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:43
*/
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface {
@Autowired
private OrderService orderService;
@NickelValue("Nickel")
private String name;
public void test(){
System.out.println("test");
}
@Override
public void afterPropertiesSet() {
System.out.println("初始化");
System.out.println(orderService);
}
}
2.在UserService中使用NickelValue对象
package com.nickel.service;
import com.spring.Autowired;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:43
*/
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface {
@Autowired
private OrderService orderService;
@NickelValue("Nickel")
private String name;
public void test(){
System.out.println("test");
}
@Override
public void afterPropertiesSet() {
System.out.println("初始化");
System.out.println(orderService);
System.out.println(name);
}
}
3.定义实现接口BeanPostProcess的实现方法
package com.nickel.service;
import com.spring.BeanPostProcess;
import com.spring.Commponent;
import java.lang.reflect.Field;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 17:42
*/
@Commponent
public class NickelValueBeanProcess implements BeanPostProcess {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
for (Field field : bean.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(NickelValue.class)) {
field.setAccessible(true);
try {
field.set(bean,field.getAnnotation(NickelValue.class).value());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return bean;
}
}
说明:注意必须添加Commponent注解
4.执行test方法
七.bean对象中获取spring加载的beanName
7.1创建BeanNameAware接口
package com.nickel.service;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 17:53
*/
public interface BeanNameAware {
void setBeanName(String name);
}
7.2UserService实现BeanNameAware接口
package com.nickel.service;
import com.spring.Autowired;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:43
*/
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface,BeanNameAware{
@Autowired
private OrderService orderService;
@NickelValue("Nickel")
private String name;
private String beanName;
public void test(){
System.out.println("test");
System.out.println(orderService);
System.out.println(name);
System.out.println("获取beanName的值"+beanName);
}
@Override
public void afterPropertiesSet() {
System.out.println("初始化");
}
@Override
public void setBeanName(String name) {
this.beanName=name;
}
}
7.3NickelAnnotationConfigApplicationContext实现这个接口的方法
package com.spring;
import com.nickel.service.BeanNameAware;
import com.nickel.service.NickelValue;
import java.beans.Introspector;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Nickel
* @version 1.0
* @date 2023/7/5 8:20
*/
public class NickelAnnotationConfigApplicationContext {
private Class scanConfig;
private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
private Map<String,Object> singletonObjects=new HashMap<>();
private List<BeanPostProcess> beanPostProcessList=new ArrayList<>();
public NickelAnnotationConfigApplicationContext(Class scanConfig){
this.scanConfig=scanConfig;
//扫描逻辑
scan(scanConfig);
//创建bean
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName=entry.getKey();
BeanDefinition beanDefinition= entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
}
}
public Object getBean(String beanName){
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition.getScope().equals("singleton")){
Object singletonBean=singletonObjects.get(beanName);
if(singletonBean==null){
singletonBean=createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonBean);
}
return singletonBean;
}else{
return createBean(beanName,beanDefinition);
}
}
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz=beanDefinition.getType();
Object instance=null;
try {
instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
//获取方法中类型的对象
Object object= Introspector.decapitalize(field.getType().getSimpleName());
field.set(instance,getBean(object.toString()));
}
}
for (BeanPostProcess beanPostProcess : beanPostProcessList) {
instance=beanPostProcess.postProcessBeforeInitialization(instance,beanName);
}
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
if (instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
for (BeanPostProcess beanPostProcess : beanPostProcessList) {
instance=beanPostProcess.postProcessAfterInitialization(instance,beanName);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
private void scan(Class scanConfig) {
if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
String path=commponentScan.value();
path=path.replace(".","/");
//通过ApplicationContext来加载该类
ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getPath());
for (File listFile : file.listFiles()) {
String absolutePath = listFile.getAbsolutePath();
absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Commponent.class)) {
//判断是否实现BeanPostProcess方法
if (BeanPostProcess.class.isAssignableFrom(aClass)) {
BeanPostProcess beanPostProcess = (BeanPostProcess) aClass.getConstructor().newInstance();
beanPostProcessList.add(beanPostProcess);
}else{
//获取beanName
Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
String beanName=commponentAnnotation.value();
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setType(aClass);
//判断该类是单例加载还是多例加载,没有Scope注解表示多例
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
String value = annotation.value();
beanDefinition.setScope(value);
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
}
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}