有关Spring的所有文章都收录于我的专栏:👉Spring👈
目录
前置准备
第一步、创建我们自定的注解
第二步、创建我们自己的容器类
测试
总结
相关文章
| 【Spring(一)】如何获取对象(Bean) | 【Spring(一)】如何获取对象(Bean) |
| 【Spring(二)】java对象属性的配置(Bean的配置) | 【Spring(二)】java对象属性的配置(Bean的配置) |
| 【Spring(三)】熟练掌握Spring的使用 | 【Spring(三)】熟练掌握Spring的使用 |
| 【Spring(四)】Spring基于注解的配置方式 | 【Spring(四)】Spring基于注解的配置方式 |
| 【Spring(五)】引入篇:AOP的底层原理之动态代理 | 【Spring(五)】引入篇:AOP的底层原理之动态代理 |
| 【Spring(六)】使用篇:AOP在开发中的使用 | 【Spring(六)】使用篇:AOP在开发中的使用 |
在此之前我们先的了解原生Spring容器中有什么,以及它们的功能都是什么,我们才能有目的实现它。我们先在Spring容器中注入一个Bean。



这个注解用于标注配置类。我们手写的Spring容器使用的都是基于注解的方式。这个配置类就相当于我们的XML配置文件中配置扫描的包的路径。
package com.jl.spring.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author long* @date 2022/9/4* @Target 指定我们的Component注解可以修饰Type程序元素*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {String value() default "";
}
此注解用于标注Bean对象。我们这里只写一个@Component`,其他例如:@Service这些都是相同的原理。
package com.jl.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 Component {// 可以通过此注解指定bean的id值String value() default "";
}
此注解用于声明Bean为单例还是多例。
package com.jl.spring.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 可以指定bean的作用范围* singleton,prototype*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {String value() default "";
}
用于自动装配的注解。
package com.jl.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 {// 可以通过此注解指定bean的id值
// String value() default "";
}
用于标注切面类的注解。
package com.jl.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 Aspect {String value() default "";
}
前置通知的注解。
package com.jl.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})
@Retention(RetentionPolicy.RUNTIME)
public @interface Before {String value();String argNames() default "";
}
返回通知的注解。
package com.jl.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})
@Retention(RetentionPolicy.RUNTIME)
public @interface AfterReturning {String value() default "";String pointcut() default "";String returning() default "";String argNames() default "";
}
后置通知的注解。
package com.jl.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})
@Retention(RetentionPolicy.RUNTIME)
public @interface After {String value();String argNames() default "";
}
在【一】中我们可以看到原生Spring容器中有几个很重要的属性:
beanDefinitionMap :用于存放Bean的配置信息。singletonObjects:存放创建好的Bean实例。beanPostProcessorList:我们这里再添加到一个存放后置处理器的数组。private Class configClass;
// 定义属性BeanDefinitionMap->存放BeanDefinition对象
private ConcurrentHashMap beanDefinitionMap = new ConcurrentHashMap<>();
// 定义属性SingletonObjects->存放单例对象
private ConcurrentHashMap singletonObjects= new ConcurrentHashMap<>();
// 定义属性,存放我们的后置处理器
private List beanPostProcessorList = new ArrayList<>();
// 该方法完成对指定包的扫描,并将Bean信息封装到BeanDefinition对象,再放入Map中
public void beanDefinitionByScan(Class configClass){this.configClass = configClass;//1. 获取要扫描的包ComponentScan componentScan =(ComponentScan)this.configClass.getDeclaredAnnotation(ComponentScan.class);//2. 通过ComponentScan的value =》即要扫描的包String path = componentScan.value();//得到要扫描包下的所有资源(.class)//1) 得到类的加载器ClassLoader classLoader = JlSpringApplicationContext.class.getClassLoader();//2) 通过类的加载器获取到要扫描的包的资源urlpath = path.replace(".","/");URL resource = classLoader.getResource(path);//3) 将要加载的资源(.class)路径下的文件进行遍历=》ioFile file = new File(resource.getFile());if (file.isDirectory()){File[] files = file.listFiles();for (File f : files) {//class文件的绝对路径String fileAbsolutePath = f.getAbsolutePath();// 这里我们进行过滤,只处理.class文件if (fileAbsolutePath.endsWith(".class")) {//1. 获取到类名String className = fileAbsolutePath.substring(fileAbsolutePath.lastIndexOf("\\") + 1, fileAbsolutePath.indexOf(".class"));//2. 获取类的全路径String classFullName = path.replace("/", ".") + "." + className;//3. 判断该.class文件是不是需要注入到容器中;看该类是不是有注解@Component @Servicetry {//这是我们就得到了该类的Class对象// 这里也可以通过class.forName得到一个Class对象// 区别是:class.forName()会调用类的静态方法,classLoader.loadClass()不会Class> clazz = classLoader.loadClass(classFullName);//aClass.isAnnotationPresent(Component.class) 判断该类是否有@Component注解if (clazz.isAnnotationPresent(Component.class)){System.out.println("这是一个SpringBean=" + clazz + " 类名=" + className);// 为了方便,我们将后置处理器放入集合中(真实的还是在走createBean和getBean这些逻辑,这里是简化的)// 如果是一个后置处理器就放入集合中// 这里我们不能通过instanceof来判断是否实现了BeanPostProcessor// 原因:这个的clazz是一个类对象,不是一个实例对象if (BeanPostProcessor.class.isAssignableFrom(clazz)){BeanPostProcessor beanPostProcessor = (BeanPostProcessor)clazz.newInstance();beanPostProcessorList.add(beanPostProcessor);continue;}//先得到beanName// 1. 得到component注解Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);// 2. 得到value值(1.配置了value 2.没有配置value)String beanName = declaredAnnotation.value();if ("".equals(beanName)){ // 如果没有写value// 将该类的类名首字母小写作为beanNamebeanName = StringUtils.uncapitalize(className);}// 3. 将bean的信息封装到BeanDefinition对象BeanDefinition beanDefinition = new BeanDefinition();beanDefinition.setClazz(clazz);// 4. 获取scope的值if(clazz.isAnnotationPresent(Scope.class)){// 如果有scope值Scope scopeAnnotation = clazz.getDeclaredAnnotation(Scope.class);beanDefinition.setScope(scopeAnnotation.value());}else { //如果没有scope值beanDefinition.setScope("singleton");}// 5. 将BeanDefinition放入到Map中beanDefinitionMap.put(beanName,beanDefinition);}else {System.out.println("这不是一个SpringBean=" + clazz + " 类名" + className);}} catch (Exception e) {e.printStackTrace();}}}}
}
配置类。我们这里将配置类的Class对象作为参数传递给我们的容器类的构造器(这一步在容器的构造器中体现)。Class对象之后,我们就可以通过@ComponentScan拿到要扫描类的路径。@Component。只有加了此注解的将来才可以注入到容器中。@Component,那么还得判断它是否是后置处理器,如何是后置处理器,实例化之后就将其直接加入到后置处理器集合中。@Component中的value值。如果没有value值为空,就默认按照id=类名首字母小写的方式命名。如果value值不为空,就将获取到的value值作为id。@Scope。如果有就拿到它的value值,反之就默认为singleton(单例)。最后将此信息存入到BeanDefinition中。BeanDefinition结构:package com.jl.spring.ioc;
/*** 用于记录bean的信息(bean为单例还是多例Scope;bean对应的class对象,反射可以生成对应的对象)**/
public class BeanDefinition {private String scope;private Class clazz;public BeanDefinition(String scope, Class clazz) {this.scope = scope;this.clazz = clazz;}public BeanDefinition() {}@Overridepublic String toString() {return "BeanDefinition{" +"scope='" + scope + '\'' +", clazz=" + 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;}
}
beanName(也就是id值)和beanDefinition(记录单例还是多例),存到我们的beanDefinitionMap。在上一步中我们对所有的类进行了扫描,并且将所有Bean的信息存入到了beanDefinitionMap中。接下来我们就可以创建Bean实例了。
// 完成 createBean(BeanDefinition beanDefinition)方法
private Object createBean(String beanName,BeanDefinition beanDefinition){// 得到bean的class对象Class clazz = beanDefinition.getClazz();// 使用反射得到实例try {Object instance = clazz.getDeclaredConstructor().newInstance();// 注入对象// 1. 遍历当前要创建的对象的所有字段for (Field declaredField : clazz.getDeclaredFields()){//2. 判断该字段是否有Autowired修饰if (declaredField.isAnnotationPresent(Autowired.class)){// 3.得到字段的名称String name = declaredField.getName();// 4.通过getBean方法来获取要组装对象Object bean = getBean(name);// 5. 进行组装// 因为属性是私有的,所以要暴破declaredField.setAccessible(true);declaredField.set(instance,bean);}}System.out.println("创建好了一个实例" + instance);// 我们在Bean的初始化方法前,调用我们后置处理器的before方法for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {// 在后置处理器的before方法,可以对容器生成的bean进行处理// 然后返回处理后的bean实例Object current = beanPostProcessor.postProcessBeforeInitialization(instance,beanName);if (current != null){instance = current;}}//判断是否需要执行Bean的初始化方法// 1. 判断当前创建的Bean对象是否实现了InitializingBeanif (instance instanceof InitializingBean){ //如果实现了InitializingBean// 将 instance转成接口类型try {((InitializingBean)instance).afterPropertiesSet();} catch (Exception e) {e.printStackTrace();}}// 我们在Bean的初始化方法前,调用我们后置处理器的after方法for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {// 在后置处理器的after方法,可以对容器生成的bean进行处理// 然后返回处理后的bean实例Object current = beanPostProcessor.postProcessAfterInitialization(instance,beanName);if (current != null){instance = current; }}System.out.println("-----------------------------------------");return instance;} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}// 如果反射对象失败,则返回空return null;
}
BeanDefinition中拿到需要创建的Class对象。Field对象数组,遍历判断是否有@Autowired。如果有就拿到此属性的名称,以此名称作为id去获取容器中的创建好的Bean实例。最后通过反射完成对属性的赋值。这里还得对属性进行暴破,因为属性是私有的.后置处理器和初始化类。BeanPostProcessor结构:package com.jl.spring.processor;import org.apache.commons.lang.StringUtils;/*** 参考原生Spring容器定义的一个接口* 该接口有两个方法*/
public interface BeanPostProcessor {/*** 这连个方法会对所有的bean生效* 该方法在bean的初始化方法前调用* @param bean* @param beanName* @return*/default Object postProcessBeforeInitialization(Object bean, String beanName){return bean;};/*** 该方法在bena的初始化方法之后调用* @param bean* @param beanName* @return*/default Object postProcessAfterInitialization(Object bean, String beanName){return bean;};
}
beanPostProcessorList(后置处理器集合),调用它们的postProcessBeforeInitialization(),实现对Bean实例的前置处理。InitializingBean。如果实现了,执行它的afterPropertiesSet()。InitializingBean结构如下:package com.jl.spring.processor;/*** 根据原生Spring定义一个接口* 这个接口有一个方法* afterPropertiesSet在Bean的Setter方法后执行,即就是我们的初始化方法* 当一个Bean实现这个接口后,就实现afterPropertiesSet*/
public interface InitializingBean {void afterPropertiesSet() throws Exception;
}
beanPostProcessorList(后置处理器集合),调用它们的postProcessAfterInitialization(),实现对Bean实例的后置处理。// 编写方法返回容器的对象
public Object getBean(String name){// 判断传入的beanName是否在beanDefinition中存在if (beanDefinitionMap.containsKey(name)){BeanDefinition beanDefinition = beanDefinitionMap.get(name);// 得到beanDefinition的scope,分别进行处理if("singleton".equalsIgnoreCase(beanDefinition.getScope())){// 单例的,直接从单例池中获取return singletonObjects.get(name);}else { // 如果不是单例,就通过createBean,反射一个对象return createBean(name,beanDefinition);}}else {// 如果不存在throw new NullPointerException("没有该bean");}
}
singletonObjects中获取。如果不是就调用createBean(),造一个Bean实例返回。public JlSpringApplicationContext(Class configClass){beanDefinitionByScan(configClass);// 通过beanDefinition对象,初始化singletonObject单例池Enumeration keys = beanDefinitionMap.keys();// 遍历所有的beanDefinition对象while (keys.hasMoreElements()){String beanName = keys.nextElement();// 通过beanName得到对应的beanDefinition对象BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);// 判断该bean是singleton还是一个prototypeif ("singleton".equalsIgnoreCase(beanDefinition.getScope())){// 将该bean实例放入到singletonObjects这个集合中Object bean = createBean(beanName,beanDefinition);singletonObjects.put(beanName,bean);}}
// System.out.println("单例池" + singletonObjects);
}
配置类
package com.jl.spring.ioc;import com.jl.spring.annotation.ComponentScan;/*** 这是一个配置类,作用类似我们原生spring的beans.xml 容器配置文件*/
@ComponentScan(value = "com.jl.spring.component")
public class JlSpringConfig {
}
测试类:
package com.jl.spring;import com.jl.spring.component.MonsterService;
import com.jl.spring.component.SmartAnimalable;
import com.jl.spring.ioc.JlSpringApplicationContext;
import com.jl.spring.ioc.JlSpringConfig;public class AppMain {public static void main(String[] args) {JlSpringApplicationContext jlSpringApplicationContext =new JlSpringApplicationContext(JlSpringConfig.class);Object car = jlSpringApplicationContext.getBean("car");System.out.println(car);}
}
结果截图:

package com.jl.spring.component;import com.jl.spring.annotation.Component;@Component(value = "myCar")
public class Car {
}
测试类:
package com.jl.spring;import com.jl.spring.component.MonsterService;
import com.jl.spring.component.SmartAnimalable;
import com.jl.spring.ioc.JlSpringApplicationContext;
import com.jl.spring.ioc.JlSpringConfig;public class AppMain {public static void main(String[] args) {JlSpringApplicationContext jlSpringApplicationContext =new JlSpringApplicationContext(JlSpringConfig.class);Object car = jlSpringApplicationContext.getBean("myCar");System.out.println(car);}
}
结果截图:

package com.jl.spring.component;import com.jl.spring.annotation.Component;
import com.jl.spring.processor.InitializingBean;@Component(value = "monsterDao")
public class MonsterDao implements InitializingBean {public void hi(){System.out.println("MonsterDao-hi()被调用。。。");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("MonsterDao初始化方法被调用");}
}
package com.jl.spring.component;import com.jl.spring.annotation.Autowired;
import com.jl.spring.annotation.Component;
import com.jl.spring.annotation.Scope;
import com.jl.spring.processor.InitializingBean;/*** MonsterService是一个service*/
@Component(value = "monsterService") // 把MonsterService注入到我们自己的Spring容器中
public class MonsterService implements InitializingBean {@Autowiredprivate MonsterDao monsterDao;public void m1(){monsterDao.hi();}/*** 该方法就是Bean的方法执行过后,被容器调用* 即就是初始化方法* @throws Exception*/@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("MonsterService初始化方法被调用");}
}
测试类:
package com.jl.spring;import com.jl.spring.component.MonsterService;
import com.jl.spring.component.SmartAnimalable;
import com.jl.spring.ioc.JlSpringApplicationContext;
import com.jl.spring.ioc.JlSpringConfig;public class AppMain {public static void main(String[] args) {JlSpringApplicationContext jlSpringApplicationContext =new JlSpringApplicationContext(JlSpringConfig.class);Object bean = jlSpringApplicationContext.getBean("monsterService");System.out.println(bean);}
}
结果截图:

package com.jl.spring.component;import com.jl.spring.annotation.Autowired;
import com.jl.spring.annotation.Component;
import com.jl.spring.annotation.Scope;
import com.jl.spring.processor.InitializingBean;/*** MonsterService是一个service*/
@Component(value = "monsterService") // 把MonsterService注入到我们自己的Spring容器中
@Scope(value = "prototype")
public class MonsterService implements InitializingBean {@Autowiredprivate MonsterDao monsterDao;public void m1(){monsterDao.hi();}/*** 该方法就是Bean的方法执行过后,被容器调用* 即就是初始化方法* @throws Exception*/@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("MonsterService初始化方法被调用");}
}
测试类
package com.jl.spring;import com.jl.spring.component.MonsterService;
import com.jl.spring.component.SmartAnimalable;
import com.jl.spring.ioc.JlSpringApplicationContext;
import com.jl.spring.ioc.JlSpringConfig;public class AppMain {public static void main(String[] args) {JlSpringApplicationContext jlSpringApplicationContext =new JlSpringApplicationContext(JlSpringConfig.class);Object bean = jlSpringApplicationContext.getBean("monsterService");Object bean1 = jlSpringApplicationContext.getBean("monsterService");System.out.println(bean);System.out.println(bean1);}
}
结果截图:

package com.jl.spring.component;import com.jl.spring.annotation.Component;
import com.jl.spring.processor.InitializingBean;@Component(value = "myCar")
public class Car implements InitializingBean {public Car() {System.out.println("Car无参构造被调用...");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("初始化方法");}
}
package com.jl.spring.component;import com.jl.spring.annotation.Component;
import com.jl.spring.processor.BeanPostProcessor;@Component
public class BeanPostProcessorImpl implements BeanPostProcessor{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {System.out.println("前置通知");return null;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {System.out.println("后置通知");return null;}
}
测试类:
package com.jl.spring;import com.jl.spring.component.MonsterService;
import com.jl.spring.component.SmartAnimalable;
import com.jl.spring.ioc.JlSpringApplicationContext;
import com.jl.spring.ioc.JlSpringConfig;public class AppMain {public static void main(String[] args) {JlSpringApplicationContext jlSpringApplicationContext =new JlSpringApplicationContext(JlSpringConfig.class);Object car = jlSpringApplicationContext.getBean("myCar");System.out.println(car);}
}
结果截图:

我们AOP和后置处理器有所联系。AOP就是利用前后置处理器进行切面处理。单例加强。
我们先看一下,用后置处理器实现的切面。
package com.jl.spring.component;public interface SmartAnimalable {float getSum(float i ,float j);float getSub(float i ,float j);
}
package com.jl.spring.component;import com.jl.spring.annotation.Component;@Component(value="smartDog")
public class SmartDog implements SmartAnimalable{@Overridepublic float getSum(float i, float j) {float res = i+j;System.out.println("SmartDog-getSum-res=" + res);return res;}@Overridepublic float getSub(float i, float j) {float res = i -j;System.out.println("SmartDog-getSub-res=" + res);return res;}
}
后置处理器实现类:
package com.jl.spring.component;import com.jl.spring.annotation.Component;
import com.jl.spring.processor.BeanPostProcessor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 这是我们自己的后置处理器* 它是实现了BeanPostProcessor* 我们可以重写里边的方法* 在Spring容器中仍然将我们的后置处理器当作一个Bean来处理,要注入到容器中* 还得考虑多个后置处理器的情况*/
@Component
public class JlBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {System.out.println("后置处理器的JlBeanPostProcessor的before()方法被调用" + bean.getClass() + " beanName=" + beanName);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {System.out.println("后置处理器的JlBeanPostProcessor的after()方法被调用" + bean.getClass() + " beanName=" + beanName);// 实现AOP,返回代理对象,即对Bean进行包装if("smartDog".equals(beanName)){// 使用JDK的动态代理,返回Bean的代理对象Object proxyInstance = Proxy.newProxyInstance(JlBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("method"+ method.getName());Object result = null;// 加入要进行前置通知处理的方法是getSumif ("getSum".equals(method.getName())){SmartAnimalAspect.showBeginLog();result = method.invoke(bean,args);// 进行返回通知的处理SmartAnimalAspect.showSuccessLog();}else {result = method.invoke(bean,args);}return result;}});// 如果bean是需要返回代理对象的,这里就直接返回代理对象return proxyInstance;}// 如果不需要AOP处理,我们就返回原生对象return bean;}
}
看到这里不知道小伙伴们有种似曾相识的感juo。没错!这里就是我们【AOP引入篇】中提到的动态代理。我们因为是简单演示,所以这里只是在postProcessAfterInitialization()中做了处理。
测试类:
package com.jl.spring;import com.jl.spring.component.MonsterService;
import com.jl.spring.component.SmartAnimalable;
import com.jl.spring.ioc.JlSpringApplicationContext;
import com.jl.spring.ioc.JlSpringConfig;public class AppMain {public static void main(String[] args) {JlSpringApplicationContext jlSpringApplicationContext =new JlSpringApplicationContext(JlSpringConfig.class);// 测试AOP是否生效SmartAnimalable smartDog = (SmartAnimalable)jlSpringApplicationContext.getBean("smartDog");smartDog.getSum(10,2);smartDog.getSub(10,2);System.out.println(smartDog.getClass());}
}
结果截图:

我们只对getSum做了增强,所以结果显示也只是对getSum的增强。
其实真正的AOP也和这个很类似,但他对很多内容进行了封装。我们下边模拟一个AOP:
package com.jl.spring.component;public interface SmartAnimalable {float getSum(float i ,float j);float getSub(float i ,float j);
}
切面类
package com.jl.spring.component;import com.jl.spring.annotation.*;/*** 先将SmartAnimalAspect当作一个切面类来使用* 后面再改的更加灵活*/
@Aspect
@Component
public class SmartAnimalAspect {@Before(value = "execution float com.jl.spring.component.SmartDog.getSum")public static void showBeginLog(){System.out.println("前置通知");}@AfterReturning(value = "execution float com.jl.spring.component.SmartDog.getSum")public static void showSuccessLog(){System.out.println("返回通知");}
}
package com.jl.spring.component;import com.jl.spring.annotation.Component;@Component(value="smartDog")
public class SmartDog implements SmartAnimalable{@Overridepublic float getSum(float i, float j) {float res = i+j;System.out.println("SmartDog-getSum-res=" + res);return res;}@Overridepublic float getSub(float i, float j) {float res = i -j;System.out.println("SmartDog-getSub-res=" + res);return res;}
}
测试类:
虽然是测试类,但这里边还对注解进行了处理,有兴趣的小伙伴可以将其抽取出来,做一些完善。
package com.jl.spring;import com.jl.spring.annotation.AfterReturning;
import com.jl.spring.annotation.Before;
import com.jl.spring.component.SmartAnimalAspect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class JlTest {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {Class smartAnimalAspectClass = SmartAnimalAspect.class;for (Method declaredMethod : smartAnimalAspectClass.getDeclaredMethods()) {if(declaredMethod.isAnnotationPresent(Before.class)){String name = declaredMethod.getName();Before annotation = declaredMethod.getAnnotation(Before.class);String value = annotation.value();Method declaredMethod1 = smartAnimalAspectClass.getDeclaredMethod(declaredMethod.getName());declaredMethod1.invoke(smartAnimalAspectClass.newInstance(),null);}else if(declaredMethod.isAnnotationPresent(AfterReturning.class)){String name = declaredMethod.getName();Before annotation = declaredMethod.getAnnotation(Before.class);String value = annotation.value();Method declaredMethod1 = smartAnimalAspectClass.getDeclaredMethod(declaredMethod.getName());declaredMethod1.invoke(smartAnimalAspectClass.newInstance(),null);}}}
}
结果截图:

以上就是我们手写的一个简易的Spring,主要是帮助大家理解Spring的基本执行流程。
如果文章中有描述不准确或者错误的地方,还望指正。您可以留言📫或者私信我。🙏
最后希望大家多多 关注+点赞+收藏^_^,你们的鼓励是我不断前进的动力!!!
感谢感谢~~~🙏🙏🙏