java-spring 图灵 02 手写spring

news2025/2/5 2:51:58

01.idea中创建一个maven管理的空项目
在这里插入图片描述
02.模拟创建出spring容器类,这里叫wzpApplicationContext,创建的时候会自动加载配置类的数据:

这里wzpApplicationContext对标的是AnnotationConfigApplicationContext

public class wzpApplicationContext {
    private Class configClass;

    public wzpApplicationContext(Class configClass) {
        this.configClass = configClass;
    }
}

模拟出容器类要扫描的配置类Appconfig

public class Appconfig {
}

在test中去测试这些创建的类

public class Mytest {
 public static void main(String[] args) {
    wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);
}
}

03.在wzpApplicationContext 添加getbean函数,获取spring容器中的bean

  public Object getBean(String beanName) {
        return null;
    }

创建服务类UserService

public class UserService {
}

在这里插入图片描述

在测试test中运行getbean方法

public class Mytest {
 public static void main(String[] args) {
    wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);

    UserService userService=   (UserService)wzpApplicationContext.getBean("UserService");
}
}

04.在服务类中写一些方法,等会看一下是不是可以运行

public class UserService {
    public void test(){
        System.out.println("test");
    }
}

此时在test中:

public class Mytest {
    public static void main(String[] args) {
        wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);

        UserService userService=   (UserService)wzpApplicationContext.getBean("UserService");

        userService.test();
    }

}

05.写几个自定义的注解
比如说,spring容器中的扫描,需要注解@ComponentScan
在这里插入图片描述

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {

    String value() default "";
}

解释一下:
Target 注解是说,这个注解主要用在哪一个区域,TYPE表示类,FIELD表示属性,METHOD表示方法。
Rentention 注解是说,这个注解在那个阶段使用,RUNTIME是在类加载阶段使用

然后模仿spring去用:

@ComponentScan("org.example.wzp.service")
public class Appconfig {
    
}

再创建一个注解:@Component

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
    String value() default "";
}

在服务类中去使用:

@Component
public class UserService {
    public void test(){
        System.out.println("test");
    }
}

06.实现扫描的功能
现在只是写了几个注解,具体的功能代码还没有写,接下来就是扫描的代码
回想spring框架,是创建spring容器的时候,就会自动创建bean
所以,扫描的具体实现代码就应该在构造函数中写


        //判断类上是不是有注解ComponentScan

        if(configClass.isAnnotationPresent(ComponentScan.class)){

            //获取注解对象

            ComponentScan componentScan = (ComponentScan)configClass.getAnnotation(ComponentScan.class);

            //获取注解对象上的value,这里也就是path
            String path = componentScan.value();

            //文件的路径是/,而获取到的是带有.的包名

            path=path.replace(".","/");

            //获取当前的类加载器
            ClassLoader classLoader = wzpApplicationContext.class.getClassLoader();
            //根据类加载器获取编译完成的target的class文件夹的路径

            URL resource = classLoader.getResource(path);
            //根据路径,获取文件

            File file=new File(resource.getFile());
            //因为扫描的是包,所以大概率是一个目录

            if (file.isDirectory()){
                //获取目录中的文件集合

                for (File f:file.listFiles()){
                    //获取文件的绝对路径
                    String absolutePath = f.getAbsolutePath();
                    //截取从org到class
                    String org = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));
                    //由于是文件路径,要转换回来,把\变成 . 包名,好让类加载器加载得到类的对象
                    String classpath = org.replace("\\", ".");
                    //加载器加载后,得到一个类对象
                    Class<?> aClass = classLoader.loadClass(classpath);
                    //判断是不是类上存在Component注解
                    if(aClass.isAnnotationPresent(Component.class)){

                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                            }
                            else{
                                //多例模式
                            }

                        }
                    }

                }
            }

        }
    }

创建一个注解 Scope

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
    String value() default "";
}

在服务类上使用,如果是单例,就写singleton,如果是多例,就写prototype

例如:服务类UserService ,这里声明是单例模式

@Component("UserService")
@Scope("singleton")
public class UserService {
    public void test(){
        System.out.println("test");
    }
}

07.优化设计,把类上注解的许多信息都放入到一个对象中的话,直接去读取这个类的属性就好了

创建一个BeanDefinition

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;
     }

}


再次优化扫描

 //判断是不是类上存在Component注解
                    if(aClass.isAnnotationPresent(Component.class)){
                    
                        Component componentAnnotation = aClass.getAnnotation(Component.class);

                        String name = componentAnnotation.value();


                        BeanDefinition beanDefinition=new BeanDefinition();

                        beanDefinition.setType(aClass);
                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();
                            
                            beanDefinition.setScope(value);

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                                beanDefinition.setScope("singleton");
                            }
                            else{
                                //多例模式
                            }

                        }
                    }

在wzpApplicationContext 中添加一个属性,map集合

public class wzpApplicationContext {
//配置类
    private Class configClass;
//存放BeanDefinition
    private Map<String,BeanDefinition> BeanDefinitionMap =new HashMap<>();
    }

把刚刚创建的BeanDefinition放入到map集合中:

if(aClass.isAnnotationPresent(Component.class)){

                        Component componentAnnotation = aClass.getAnnotation(Component.class);

                        String name = componentAnnotation.value();

                        BeanDefinition beanDefinition=new BeanDefinition();

                        beanDefinition.setType(aClass);
                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();

                            beanDefinition.setScope(value);

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                                beanDefinition.setScope("singleton");
                            }
                            else{
                                //多例模式
                            }
                            BeanDefinitionMap.put(name,beanDefinition);

                        }
                    }

最后总的代码抽象此外一个方法:
在这里插入图片描述

   public wzpApplicationContext(Class configClass) throws ClassNotFoundException {
        this.configClass = configClass;


        //判断类上是不是有注解ComponentScan

        scan(configClass);
    }

   private void scan(Class configClass) throws ClassNotFoundException {
        if(configClass.isAnnotationPresent(ComponentScan.class)){

            //获取注解对象

            ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);

            //获取注解对象上的value,这里也就是path
            String path = componentScan.value();

            //文件的路径是/,而获取到的是带有.的包名

            path.replace(".","/");

            //获取当前的类加载器
            ClassLoader classLoader = wzpApplicationContext.class.getClassLoader();
            //根据类加载器获取编译完成的target的class文件夹的路径

            URL resource = classLoader.getResource(path);
            //根据路径,获取文件

            File file=new File(resource.getFile());
            //因为扫描的是包,所以大概率是一个目录

            if (file.isDirectory()){
                //获取目录中的文件集合

                for (File f:file.listFiles()){
                    //获取文件的绝对路径
                    String absolutePath = f.getAbsolutePath();
                    //截取从org到class
                    String org = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));
                    //由于是文件路径,要转换回来,把\变成 . 包名,好让类加载器加载得到类的对象
                    String classpath = org.replace("\\", ".");
                    //加载器加载后,得到一个类对象
                    Class<?> aClass = classLoader.loadClass(classpath);
                    //判断是不是类上存在Component注解
                    if(aClass.isAnnotationPresent(Component.class)){

                        Component componentAnnotation = aClass.getAnnotation(Component.class);

                        String name = componentAnnotation.value();

                        BeanDefinition beanDefinition=new BeanDefinition();

                        beanDefinition.setType(aClass);
                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();

                            beanDefinition.setScope(value);

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                                beanDefinition.setScope("singleton");
                            }
                            else{
                                //多例模式
                            }
                            BeanDefinitionMap.put(name,beanDefinition);

                        }
                    }

                }
            }

        }
    }

08.扫描完了,开始写createbean方法了
在扫描之后调用:
用for循环

public class wzpApplicationContext {
    private Class configClass;

    private Map<String,BeanDefinition> BeanDefinitionMap =new HashMap<>();

    public wzpApplicationContext(Class configClass) throws ClassNotFoundException {
        this.configClass = configClass;


        //判断类上是不是有注解ComponentScan

        scan(configClass);
		for (Map.Entry<String, BeanDefinition> entry : BeanDefinitionMap.entrySet()){
            BeanDefinition beanDefinition = entry.getValue();
            String beanName = entry.getKey();
            if (beanDefinition.getScope().equals("singleton"))
            {
            //在这里调用createbean,创建单例
              Object bean=  createBean(beanName,beanDefinition);
            
            }
        }
}

09.在wzpApplicationContext 创建createBean

  private Object createBean(String beanName, BeanDefinition beanDefinition) {
        return null;
    }

10.创建的bean要保存到容器

在wzpApplicationContext 创建一个属性 Map<String,Object> singletonObjectsMap,这个用来保存创建的单例bean

  //保存单例的地方,Map集合
    private Map<String,Object> singletonObjectsMap =new HashMap<>();

此时的for循环

 for (Map.Entry<String, BeanDefinition> entry : BeanDefinitionMap.entrySet()){
            BeanDefinition beanDefinition = entry.getValue();
            String beanName = entry.getKey();
            if (beanDefinition.getScope().equals("singleton"))
            {
            //创建单例
              Object  bean=  createBean(beanName,beanDefinition);
             //保存单例到容器中 
              singletonObjectsMap.put(beanName,bean);
            }
        }

11.什么时候调用这个getbean方法

先从BeanDefinitionMap获取已经扫描完了beanDefinition,如果有的话,那表示在扫描的包中,有这个类,再判断是不是单例模式,如果没有的话,那就说明没有这样的类,抛出异常。

  public Object getBean(String beanName) throws Exception {

        if (!BeanDefinitionMap.containsKey(beanName)){
            throw new NullPointerException();
        }

        BeanDefinition beanDefinition = BeanDefinitionMap.get(beanName);

        if (beanDefinition.getScope().equals("singleton"))
        {
            //单例
			
        }else{
            //原型
        }

        return null;
    }

这里是获取bean,单例从容器中获取

singletonObjectsMap.get(beanName)

原型(多例)就马上创建一个bean

createBean(beanName, beanDefinition);

这个时候的getBean方法

    public Object getBean(String beanName) throws Exception {

        if (!BeanDefinitionMap.containsKey(beanName)){
            throw new NullPointerException();
        }

        BeanDefinition beanDefinition = BeanDefinitionMap.get(beanName);

        if (beanDefinition.getScope().equals("singleton"))
        {
            //单例
            return     singletonObjectsMap.get(beanName);
        }else{
            //原型
            Object bean = createBean(beanName, beanDefinition);
            return bean;

        }

       
    }

12.如何创建bean呢,用反射 newInstance()

   private Object createBean(String beanName, BeanDefinition beanDefinition) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = beanDefinition.getType();
        Object o = clazz.getConstructor().newInstance();

        return o;
    }

13.测试
在这里插入图片描述
14.创建一个多例

@Component("OrderService")
@Scope("prototype")
public class OrderService
{
}

public class Mytest {
    public static void main(String[] args) throws Exception {
        wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);

        UserService userService=   (UserService)wzpApplicationContext.getBean("UserService");
        System.out.println((UserService)wzpApplicationContext.getBean("UserService"));
        System.out.println((UserService)wzpApplicationContext.getBean("UserService"));
        System.out.println((UserService)wzpApplicationContext.getBean("UserService"));
        System.out.println((OrderService)wzpApplicationContext.getBean("OrderService"));
        System.out.println((OrderService)wzpApplicationContext.getBean("OrderService"));
        System.out.println((OrderService)wzpApplicationContext.getBean("OrderService"));
        userService.test();
    }

}

在这里插入图片描述
15.实现依赖注入:也就是@AutoWired注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface AutoWired {
}

在服务类UserService中使用这个自定义的注解:

@Component("UserService")
@Scope("singleton")
public class UserService {
    
    @AutoWired
    private OrderService orderService;
    public void test(){
        System.out.println("test");
    }
}

16.测试

结果是null
在这里插入图片描述
17.实现依赖注入
在createBean方法中去写:

private Object createBean(String beanName, BeanDefinition beanDefinition) throws Exception {
        Class clazz = beanDefinition.getType();
        Object o = clazz.getConstructor().newInstance();


        for (Field field : clazz.getDeclaredFields())
        {
            if (field.isAnnotationPresent(AutoWired.class))
            {
                //将该对象的可访问标志设置为指定的布尔值。值为true表示当使用该反射对象时应该抑制Java语言访问检查。
                //实际上setAccessible是启用和禁用访问安全检查的开关
                //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的
                field.setAccessible(true);
                //Field.set()方法的语法:
                //   set(Object obj, Object value)
                //      此时的Field对象表示已经是这个对象的一个属性了  为Field对象属于的变量的属性设置新值(Field代表的属性的新的值)

                field.set(o,getBean(field.getName()));
            }
        }


        return o;
    }

18.存在一个问题,实现依赖注入的时候,万一那个对象还没有被创建呢,也就是在容器中还没有来得及创建这个类型的bean,要修改getbean方法

public Object getBean(String beanName) throws Exception {

        if (!BeanDefinitionMap.containsKey(beanName)){
            throw new NullPointerException();
        }

        BeanDefinition beanDefinition = BeanDefinitionMap.get(beanName);

        if (beanDefinition.getScope().equals("singleton"))
        {
          Object singletOnobjectBean=  singletonObjectsMap.get(beanName);
            //单例
            if (singletOnobjectBean==null){
                singletonObjectsMap.put(beanName, createBean(beanName,beanDefinition)) ;
            }
            return     singletOnobjectBean;
        }else{
            //原型
            Object protoTypeBean = createBean(beanName, beanDefinition);
            
            return protoTypeBean;

        }


    }

19.实现初始化:
要写一个接口:InitializingBean

public interface InitializingBean {
     void afterPropertiesSet();
}

20.服务类UserService来实现接口:

@Component("UserService")
@Scope("singleton")
public class UserService implements InitializingBean {

    @AutoWired
    private OrderService orderService;
    public void test(){
        System.out.println(orderService);
    }

    @Override
    public void afterPropertiesSet() {
         System.out.println("初始化");
    }
}

21.初始化要在创建bean方法中去做啊,所以还是要修改createbean方法:

 private Object createBean(String beanName, BeanDefinition beanDefinition) throws Exception {
        Class clazz = beanDefinition.getType();
        Object o = clazz.getConstructor().newInstance();


        for (Field field : clazz.getDeclaredFields())
        {
            if (field.isAnnotationPresent(AutoWired.class))
            {
                //将该对象的可访问标志设置为指定的布尔值。值为true表示当使用该反射对象时应该抑制Java语言访问检查。
                //实际上setAccessible是启用和禁用访问安全检查的开关
                //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的
                field.setAccessible(true);
                //Field.set()方法的语法:
                //   set(Object obj, Object value)
                //      此时的Field对象表示已经是这个对象的一个属性了  为Field对象属于的变量的属性设置新值(Field代表的属性的新的值)

                field.set(o,getBean(field.getName()));
            }
        }
        //初始化
        if (o instanceof InitializingBean){
            ((InitializingBean) o).afterPropertiesSet();
        }

        return o;
    }

22.要实现AOP,也就要实现BeanPostProcessor,这个也是一个接口

package org.example.spring;

public interface BeanPostProcessor {


    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    default Object postProcessAfterInitialization(Object bean, String beanName)  {
        return bean;
    }
}

23.写这个接口的实现类,因为要在bean中用,所以加上@Component,表示这个也是一个bean

package org.example.spring;
@Component("wzpBeanPostProcessor")
public class wzpBeanPostProcessor  implements  BeanPostProcessor{
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return null;
    }
}


24.由于这个bean是用于AOP的,比较特殊,所以在扫描的时候创建比较好
,要修改扫描函数,主要是在扫描类中是否有@Component注解修饰的时候这一部分来写比较好

  private void scan(Class configClass) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        if(configClass.isAnnotationPresent(ComponentScan.class)){

            //获取注解对象

            ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);

            //获取注解对象上的value,这里也就是path
            String path = componentScan.value();

            //文件的路径是/,而获取到的是带有.的包名

            path= path.replace(".","/");

            //获取当前的类加载器
            ClassLoader classLoader = wzpApplicationContext.class.getClassLoader();
            //根据类加载器获取编译完成的target的class文件夹的路径

            URL resource = classLoader.getResource(path);
            //根据路径,获取文件

            File file=new File(resource.getFile());
            //因为扫描的是包,所以大概率是一个目录

            if (file.isDirectory()){
                //获取目录中的文件集合

                for (File f:file.listFiles()){
                    //获取文件的绝对路径
                    String absolutePath = f.getAbsolutePath();
                    //截取从org到class
                    String org = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));
                    //由于是文件路径,要转换回来,把\变成 . 包名,好让类加载器加载得到类的对象
                    String classpath = org.replace("\\", ".");
                    //加载器加载后,得到一个类对象
                    Class<?> aClass = classLoader.loadClass(classpath);
                    //判断是不是类上存在Component注解
                    if(aClass.isAnnotationPresent(Component.class)){

                         if (BeanPostProcessor.class.isAssignableFrom(aClass)){
                            
                            BeanPostProcessor BeanPostProcessornewInstance = (BeanPostProcessor)aClass.getConstructor().newInstance();
                            
                            BeanPostProcessorList.add(BeanPostProcessornewInstance);
                        }

                        Component componentAnnotation = aClass.getAnnotation(Component.class);

                        String name = componentAnnotation.value();

                        BeanDefinition beanDefinition=new BeanDefinition();

                        beanDefinition.setType(aClass);
                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();

                            beanDefinition.setScope(value);

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                                beanDefinition.setScope("singleton");
                            }
                            else{
                                //多例模式
                            }
                            BeanDefinitionMap.put(name,beanDefinition);

                        }
                    }

                }
            }

        }
    }

 private List<BeanPostProcessor> BeanPostProcessorList=new ArrayList<>();

25.要用这个wzpBeanPostProcessor,主要还是在createbean,这里是初始化后的操作,下面还有一个初始化前的操作

 private Object createBean(String beanName, BeanDefinition beanDefinition) throws Exception {
        Class clazz = beanDefinition.getType();
        Object o = clazz.getConstructor().newInstance();


        for (Field field : clazz.getDeclaredFields())
        {
            if (field.isAnnotationPresent(AutoWired.class))
            {
                //将该对象的可访问标志设置为指定的布尔值。值为true表示当使用该反射对象时应该抑制Java语言访问检查。
                //实际上setAccessible是启用和禁用访问安全检查的开关
                //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的
                field.setAccessible(true);
                //Field.set()方法的语法:
                //   set(Object obj, Object value)
                //      此时的Field对象表示已经是这个对象的一个属性了  为Field对象属于的变量的属性设置新值(Field代表的属性的新的值)

                field.set(o,getBean(field.getName()));
            }
        }
        //初始化
        if (o instanceof InitializingBean){
            ((InitializingBean) o).afterPropertiesSet();
        }

        //AOP
        for (BeanPostProcessor b: BeanPostProcessorList){
            //初始化后的操作
            b.postProcessAfterInitialization(o,beanName);
            
        }
        return o;
    }

在ceatebean方法
初始化前,初始化,初始化后

   //初始化后
        for (BeanPostProcessor b: BeanPostProcessorList){

            b.postProcessBeforeInitialization(o,beanName);

        }
        //初始化
        if (o instanceof InitializingBean){
            ((InitializingBean) o).afterPropertiesSet();
        }

        //初始化后
        for (BeanPostProcessor b: BeanPostProcessorList){

            b.postProcessAfterInitialization(o,beanName);

        }

26.wzpBeanPostProcessor的主要功能是AOP,怎么AOP呢,这里用的是动态代理,还要创建一个接口UserInterface

package org.example.spring;

public interface UserInterface {
    void test();
}

服务类再去实现这个接口

@Component("UserService")
@Scope("singleton")
public class UserService implements InitializingBean , UserInterface {

    @AutoWired
    private OrderService orderService;
    
    public void test(){
        System.out.println("hello AOP");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("初始化");
    }
}

27.在wzpBeanPostProcessor中去完成AOP,比如说初始化后的postProcessAfterInitialization方法中,做AOP,要针对哪个bean,用if判断:

package org.example.spring;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Component("wzpBeanPostProcessor")
public class wzpBeanPostProcessor  implements  BeanPostProcessor{
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {

        if (beanName.equals("UserService")) {
            Object proxyInstance = Proxy.newProxyInstance(wzpBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                    //执行AOP的逻辑
                    System.out.println("hello  AOP逻辑在此");

                    //执行完了AOP的操作,执行原来的切点方法
                    return method.invoke(bean,args);
                }
            });
            return proxyInstance;
        }
        return bean;
    }
}

在createbean方法中也要修改,因为要接收代理对象

      //初始化后
        for (BeanPostProcessor b: BeanPostProcessorList){

          o=  b.postProcessBeforeInitialization(o,beanName);

        }
        //初始化
        if (o instanceof InitializingBean){
            ((InitializingBean) o).afterPropertiesSet();
        }

        //初始化后
        for (BeanPostProcessor b: BeanPostProcessorList){

           o= b.postProcessAfterInitialization(o,beanName);

        }

28.实现Aware接口

在 Spring 中,BeanNameAware 接口是一个回调接口,它提供了一个用于设置 Bean 名称的方法。当一个 Bean 实现了 BeanNameAware 接口时,在该 Bean 实例被实例化后,Spring 容器会调用 setBeanName 方法,并将该 Bean 在 Spring 容器中的名称作为参数传递进去。

创建一个BeanNameAware接口:


public interface BeanNameAware {

    void setBeanName(String name);
}

在服务类中实现接口:

package org.example.wzp.service;

import org.example.spring.*;

@Component("UserService")
@Scope("singleton")
public class UserService implements InitializingBean , UserInterface ,BeanNameAware {

    @AutoWired
    private OrderService orderService;
    public void test(){
        System.out.println("hello AOP");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("初始化");
    }
    
    private String beanName;

    @Override
    public void setBeanName(String name) {
        this.beanName=name;
    }
}

在createbean函数中:在初始化之前

  //Aware接口
        if (o instanceof BeanNameAware){

            ((BeanNameAware) o).setBeanName(beanName);
        }
        //初始化前
        for (BeanPostProcessor b: BeanPostProcessorList){

          o=  b.postProcessBeforeInitialization(o,beanName);

        }
        //初始化
        if (o instanceof InitializingBean){
            ((InitializingBean) o).afterPropertiesSet();
        }

        //初始化后
        for (BeanPostProcessor b: BeanPostProcessorList){

           o= b.postProcessAfterInitialization(o,beanName);

        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1599029.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法刷题 | 回溯思想 04】4.15(分割回文串)

文章目录 7.分割回文串7.1题目7.2解法&#xff1a;回溯7.2.1回溯思路&#xff08;1&#xff09;函数返回值以及参数&#xff08;2&#xff09;终止条件&#xff08;3&#xff09;遍历过程 7.2.2代码 7.分割回文串 7.1题目 给你一个字符串 s&#xff0c;请你将 s 分割成一些子…

鸿蒙原生应用再新丁!企查查 碧蓝航线 入局鸿蒙

鸿蒙原生应用再新丁&#xff01;企查查 碧蓝航线 入局鸿蒙 来自 HarmonyOS 微博13日消息&#xff0c;碧蓝航线 将启动鸿蒙原生应用开发&#xff0c;双方将基于HarmonyOS NEXT鸿蒙星河版的原生流畅等特性&#xff0c;进一步提升游戏流畅度和画面精美度&#xff0c;为用户提供更…

汽车零部件制造迎来智能化升级,3D视觉定位系统助力无人化生产线建设

随着新能源汽车市场的蓬勃发展&#xff0c;汽车零部件制造行业正面临着前所未有的机遇与挑战。为了提高产能和产品加工精度&#xff0c;某专业铝合金汽车零部件制造商决定引进智能生产线&#xff0c;其中&#xff0c;对成垛摆放的变速箱壳体进行机床上料成为关键一环。 传统的上…

iframe嵌入海康威视摄像头监控视频画面

前言&#xff1a;海康威视有非常好的开放平台支持(海康开放平台)&#xff0c;如遇到技术问题&#xff0c;可以先花点时间在开放平台视频教程板块学习一下。直接问客服可能会比较懵&#xff0c;而且sdk客服和api客服互相分离&#xff0c;一开始可能都不知道问谁。 在开放平台上…

《二》Qt Creator工具介绍与使用

一、关于界面 点击文件--->新建文件或项目会出现如下图&#xff1a; 我们选择第一个 点击下一步下一步&#xff1a; 继续下一步直到结束&#xff1a; 二&#xff0c;具体文件介绍 我们点击pro查看以下 QT core gui第1行 表示使用qt的core和gui库&#xff0c;如果以后…

【JAVA基础篇教学】第十四篇:Java中设计模式

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第十四篇&#xff1a;Java中设计模式。 设计模式是解决软件设计中常见问题的可重复利用的解决方案。在 Java 中&#xff0c;常见的设计模式包括单例模式、工厂模式、观察者模式等。目前在基础教学篇中只展示常见的几种模…

背会这套面试八股文!还怕拿不到offer吗?

给各位小伙伴总结了软件测试的高频面试题&#xff0c;其中包含了多个方面的知识点&#xff0c;包括&#xff1a; 测试基础(102页) Linux基础(38页) MySQL (63页) ️ web测试(28页) APP测试(38页) selenium相关(50页) 性能测试(55页) 数据结构跟算法(51页) 大厂逻辑题(…

图深度学习(一):介绍与概念

目录 一、介绍 二、图的数据结构 三、图深度学习的基本模型 四、图深度学习的基本操作和概念 五、训练过程 六、主要应用场景 七、总结 一、介绍 图深度学习是将深度学习应用于图形数据结构的领域&#xff0c;它结合了图论的概念和深度学习的技术&#xff0c;用以处理和…

二叉树的创建和遍历(java)

简介 二叉树是一种常见的树形数据结构&#xff0c;它由节点组成&#xff0c;每个节点最多有两个子节点&#xff0c;分别称为左子节点和右子节点。这些节点以层次结构的方式组织在一起&#xff0c;每个节点都有一个父节点&#xff0c;除了根节点外&#xff0c;每个节点都有一个…

SpringBoot配置profile

一、profile简介 我们在开发Spring Boot应用时&#xff0c;通常同一套程序会被安装到不同环境&#xff0c;比如:开发、测试、生产等。其中数据库地址、服务器端口等等配置都不同&#xff0c;如果每次打包时&#xff0c;都要修改配置文件&#xff0c;那么非常麻烦。profile功能就…

用Python做一个游戏辅助脚本,完整编程思路分享!

一、说明 简述&#xff1a;本文将以4399小游戏《 宠物连连看经典版2 》作为测试案例&#xff0c;通过识别小图标&#xff0c;模拟鼠标点击&#xff0c;快速完成配对。对于有兴趣学习游戏脚本的同学有一定的帮助。 运行环境&#xff1a;Win10/Python3.5。 主要模块&#xff1…

吴恩达llama课程笔记:第七课llama安全工具

羊驼Llama是当前最流行的开源大模型&#xff0c;其卓越的性能和广泛的应用领域使其成为业界瞩目的焦点。作为一款由Meta AI发布的开放且高效的大型基础语言模型&#xff0c;Llama拥有7B、13B和70B&#xff08;700亿&#xff09;三种版本&#xff0c;满足不同场景和需求。 吴恩…

C语言:文件操作(三)

目录 前言 5、文章的随机读写 5.1 fseek 5.2 ftell 5.3 rewind 结语 前言 本篇文章继续讲解文件操作&#xff0c;讲解文件的随机读写&#xff0c;主要有三个函数&#xff1a;fseek&#xff1b;ftell&#xff1b;rewind。 前面讲解的函数都是对文件内容进行顺序读写&#x…

STM32CubeMx下载安装环境搭建及工程创建

一、stm32介绍 STM32F103C8T6是一款由意法半导体公司&#xff08;ST&#xff09;推出的基于Cortex-M3内核的32位微控制器&#xff0c;硬件采用LQFP48封装&#xff0c;属于ST公司微控制器中的STM32系列。除了被我们熟知的STM32&#xff0c;ST公司还有SPC5X系列、STM8系列等&…

【C++类和对象】类和对象的引入

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

微信运动接口(获取自己的微信运动数据)

var pc new WXBizDataCrypt(appid, session_key); 这段代码是使用微信官方提供的 WXBizDataCrypt 类来解密微信运动数据。WXBizDataCrypt 是一个用于解密微信开放平台返回的加密数据的类&#xff0c;它需要传入两个参数&#xff1a;appid 和 session_key。其中&#xff0c;ap…

如何重置root用户的密码

即进入Linux操作系统的救援模式去重置密码。 1.首先重启机器&#xff0c; 2.进入grup菜单&#xff0c;按上下键盘&#xff0c;让系统的启动停在这个界面&#xff0c; 3.选择这个grup菜单的第一项&#xff0c;可以看界面下面的提示&#xff0c;按字母e编辑这个系统的启动配置…

STL —— stack、queue

博主首页&#xff1a; 有趣的中国人 专栏首页&#xff1a; C专栏 目录 1. 容器适配器 2. 栈的模拟实现 3. 队列的模拟实现 4. 双端队列deque 4.1 deque的原理介绍 4.2 deque的缺陷 4.3 为什么选择deque作为stack和queue的底层默认容器 本篇文章主要讲解 stack 和 queue …

基于SpringBoot的“银行OA系统的设计与实现”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“银行OA系统的设计与实现”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 用户登录界面 管理员主界面 员工基本档…