美文网首页
手写Spring之IOC和AOP的简易实现

手写Spring之IOC和AOP的简易实现

作者: zhemehao819 | 来源:发表于2022-01-16 20:01 被阅读0次

    仅供参考学习。

    一、手写Spring启动流程

    我们刚使用spring时,spring提供的容器是基于xml配置文件的方式:

    ClassPathXmlAplicationContext context = new ClassPathXmlAplicationContext("spring-bean.xml");
    context.getBean("userService");
    

    ClassPathXmlApplicationContext根据spring的配置文件spring-bean.xml来实例化一个spring容器,然后可以通过beanName到spring容器取到具体的bean对象。

    下面是基于注解的方式实例化一个spring容器,这篇文章也将以这种方式实现手写spring的核心功能。

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    context.getBean("userService");
    

    只不过是用一个配置类AppConfig来作为参数来实例化spring容器。

    包的约定如下:

    com.hyj.spring包:手写spring实现代码

    com.hyj.test包:验证手写spring功能代码

    :只是简易实现基本的原理,不保证健壮性,仅考虑最简单的情况。

    定义spring容器类

    package com.hyj.spring;
    
    public class HyjApplicationContext {
    
        private Class configClass;
        
        public HyjApplicationContext(Class configClass) {
            this.configClass = configClass;
        }
        
        public Object getBean(String beanName) {
            // ...
            return null;
        }
    }
    

    从上一节可以知道,它至少需要:

    • 一个参数,配置类类型
    • 一个构造方法,构造方法的参数是配置类configClass,
    • 提供一个getBean方法。

    这时候需要一个AppConfig配置类,这个配置类需要告诉我们需要扫描的包路径,那么还需要定义扫描的注解@ComponentScan

    定义配置类AppConfig

    package com.hyj.spring;
    
    @ComponentScan("com.hyj.test.service")
    public class AppConfig {
        
    }
    

    定义扫描的注解@ComponentScan

    package com.hyj.spring;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface ComponentScan {
        String value();
    }
    

    这时候假设有一个业务类UserService需要放入spring容器中,需要定义一个表示该类需要纳入Spring bean容器的注解@Component

    package com.hyj.test.service;
    
    import com.hyj.spring.Component;
    
    @Component("userService")
    @Scope("prototype")
    public class UserService {
        
    }
    

    定义表示Bean的注解@Component

    package com.hyj.spring;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface Component {
        String value();
    }
    

    定义Bean作用域的注解@Scope

    package com.hyj.spring;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface Scope {
        String value();
    }
    

    定义BeanDefinition用于解析后的bean定义

    package com.hyj.spring;
    
    public class BeanDefinition {
    
        private Class Clazz;//bean的类型
        private String scope; // bean的作用域
        //bean是否是赖加载等待...
    
        public Class getClazz() {
            return Clazz;
        }
    
        public void setClazz(Class clazz) {
            Clazz = clazz;
        }
    
        public String getScope() {
            return scope;
        }
    
        public void setScope(String scope) {
            this.scope = scope;
        }
    }
    

    spring启动流程

    1.初始化Spring容器AnnotationConfigApplicationContext时,传入Appconfig类;

    2.通过Appconfig类的@ComponentScan注解告知spring需要扫描的包路径;

    3.扫描指定包路径下的所有文件,使用类加载器加载这些classes文件;

    4.对有@Component注解的类进行解析成 BeanDefinition(Bean的定义对象);

    5.实例化所有单例bean放入单例池中;

    6.最后在getBean方法中根据具体的bean定义对象来实例化具体的bean对象;

    Bean容器实现

    package com.hyj.spring;
    
    import java.io.File;
    import java.lang.reflect.InvocationTargetException;
    import java.net.URL;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    public class HyjApplicationContext {
    
        // Spring配置类
        private Class configClass;
    
        // 单例池
        private ConcurrentHashMap<String, Object> singletonPool = new ConcurrentHashMap<>();
        // 解析到的BeanDefinition集合
        private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    
        public HyjApplicationContext(Class configClass) {
            this.configClass = configClass;
    
            // 解析配置类上的@ComponentScan注解,获取扫描的包路径
            String packagePath = getScanPackagePath(configClass);
    
            // 扫描包路径下的class文件并解析成BeanDefinition
            scanAndParseToBeanDefinitions(packagePath);
    
            // 单例bean进行实例化,并放入单例池中
            singletonInstanceToPool();
        }
    
        private void singletonInstanceToPool() {
            for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
                String beanName = entry.getKey();
                BeanDefinition beanDefinition = entry.getValue();
                if (beanDefinition.getScope().equals("singleton")) {
                    Object singletonObj = createBean(beanDefinition);
                    singletonPool.put(beanName, singletonObj);
                }
            }
        }
    
        private Object createBean(BeanDefinition beanDefinition) {
            Class clazz = beanDefinition.getClazz();
            Object o = null;
            try {
                o = clazz.getDeclaredConstructor().newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            return o;
        }
    
        private void scanAndParseToBeanDefinitions(String packagePath) {
            URL resource = HyjApplicationContext.class.getClassLoader().getResource(packagePath);//使用App加载器获取资源文件URL
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File f : file.listFiles()) { //便利所有文件
                    String absolutePath = f.getAbsolutePath();
                    if (absolutePath.endsWith(".class")) {//只扫描class文件
                        String fullyQualifiedClassName = getFullyQualifiedClassName(absolutePath);
                        try {
                            Class<?> aClass = HyjApplicationContext.class.getClassLoader().loadClass(fullyQualifiedClassName);
                            // 这个类上有@Component注解,表示当前类应该是一个bean
                            if (aClass.isAnnotationPresent(Component.class)) {
                                // 需要在扫描的时候就实例化这个bean吗?这和这个bean的作用域有关系.
                                // 解析这个类,把类的定义信息解析额出来 ---> BeanDefinition
                                parseClassToBeanDefinition(aClass);
                            }
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    
        private void parseClassToBeanDefinition(Class<?> aClass) {
            String beanName = aClass.getDeclaredAnnotation(Component.class).value();
    
            BeanDefinition beanDefinition = new BeanDefinition();
            beanDefinition.setClazz(aClass);
            if (aClass.isAnnotationPresent(Scope.class)) {//如果这个类上有@Scope注解
                beanDefinition.setScope(aClass.getDeclaredAnnotation(Scope.class).value());
            } else {
                beanDefinition.setScope("singleton"); //没有@Scope注解默认就是单例
            }
            beanDefinitionMap.put(beanName, beanDefinition); //解析到的beanDefinition放Map里
        }
    
        private String getFullyQualifiedClassName(String absolutePath) {
            String fullyQualifiedClassName = absolutePath
                    .substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"))
                    .replace(File.separator, ".");// com.hyj.test.service.UserService
            return fullyQualifiedClassName;
        }
    
        private String getScanPackagePath(Class configClass) {
            return ((ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class))
                    .value()    //扫描包名 com.hyj.test.service
                    .replace(".", File.separator);  //扫描的相对路径 com/hyj/test/service
        }
    
        public Object getBean(String beanName) {
            // 首先看BeanDefinition结合中是否有这个bean定义对象
            // 如果有,并且如果是单例,则直接从单例池中取;
            // 如果不是单例,创建bean对象
            if (beanDefinitionMap.containsKey(beanName)) {
                BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
                if (beanDefinition.getScope().equals("singleton")) {
                    return singletonPool.get(beanName);
                } else {
                    // 创建bean对象
                    Object bean = createBean(beanDefinition);
                    return bean;
                }
    
            } else {
                // 不存在对应的bean对象
                throw new NullPointerException();
            }
        }
    }
    

    其中类加载器有3种,本文使用Application的类加载器:

    BootStrap:负责加载jre/lib目录

    Ext:负责加载jre/ext/lib目录

    App:负载classpath路径

    验证测试

    package com.hyj.test;
    
    import com.hyj.spring.AppConfig;
    import com.hyj.spring.HyjApplicationContext;
    
    public class AppMain {
    
        public static void main(String[] args) {
            HyjApplicationContext applicationContext = new HyjApplicationContext(AppConfig.class);
    
            System.out.println(applicationContext.getBean("userService"));
            System.out.println(applicationContext.getBean("userService"));
        }
    }
    

    通过打印的对象是否相同来验证scope是否生效,如果生效表明整个启动过程成功。

    二、手写Spring依赖注入DI

    如果UserService里面还有成员变量对象,这时候就需要根据依赖来注入对应的属性。

    比如UserService类如下:

    package com.hyj.test.service;
    
    import com.hyj.spring.Autowired;
    import com.hyj.spring.Component;
    import com.hyj.spring.Scope;
    
    @Component("userService")
    //@Scope("prototype")
    public class UserService {
      
        @Autowired
        private OrderService orderService;
    
        public void printFiled() {
            System.out.println(orderService);
        }
    }
    

    其中,OrderService如下:

    package com.hyj.test.service;
    
    import com.hyj.spring.Component;
    import com.hyj.spring.Scope;
    
    @Component("orderService")
    public class OrderService {
    
    }
    

    用到了@Autowired注解,那么我们就来自定义一个:

    定义自动注入注解@Autowired

    package com.hyj.spring;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD, ElementType.METHOD})
    public @interface Autowired {
        /* String value() default ""; */
    }
    

    注意target指向成员变量或者方法。

    接下来改造spring容器类HyjApplicationContext里的createBean方法(根据BeanDefinition来创建)。

    改造创建Bean的方法

    HyjApplicationContext里的createBean方法:

        // 
        private Object createBean(BeanDefinition beanDefinition) {
            Class clazz = beanDefinition.getClazz();
            Object beanObj = null;
            try {
                beanObj = clazz.getDeclaredConstructor().newInstance();
    
                // 依赖注入
                for (Field declaredField : clazz.getDeclaredFields()) {
                    if (declaredField.isAnnotationPresent(Autowired.class)) { //判断成员变量是否有@Autowired注解
                        Object fieldBean = getBean(declaredField.getName()); // 根据beanName获取对应bean
                        declaredField.setAccessible(true);
                        declaredField.set(beanObj, fieldBean);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return beanObj;
        }
    
        public Object getBean(String beanName) {
            // 首先看BeanDefinition结合中是否有这个bean定义对象
            // 如果有,并且如果是单例,则直接从单例池中取;
            // 如果不是单例,创建bean对象
            if (beanDefinitionMap.containsKey(beanName)) {
                BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
                if (beanDefinition.getScope().equals("singleton")) {
                    return singletonPool.get(beanName);
                } else {
                    // 创建bean对象
                    Object bean = createBean(beanDefinition);
                    return bean;
                }
            } else {
                // 不存在对应的bean对象
                throw new NullPointerException();
            }
        }
    }
    

    验证依赖注入

    public class AppMain {
        public static void main(String[] args) {
            HyjApplicationContext applicationContext = new HyjApplicationContext(AppConfig.class);
    
            UserService userService = (UserService) applicationContext.getBean("userService");
            userService.printFiled();
        }
    }
    

    查看userService的成员变量orderService是否有值。

    三、手写Spring之Aware回调

    如果在UserService里有一个beanName的属性需要注入,此时如果用@Autowired注入显然不合适,Spring的bean容器中没有这这个bean,可以使用Aware进行回调。

    @Component("userService")
    public class UserService {
    
        @Autowired
        private OrderService orderService;
    
        private String beanName;
    
        public void printFiled() {
            System.out.println(orderService);
        }
    }
    

    定义BeanNameAware接口

    package com.hyj.spring;
    
    public interface BeanNameAware {
        void setBeanName(String beanName);
    }
    

    实现BeanNameAware接口

    package com.hyj.test.service;
    
    import com.hyj.spring.Autowired;
    import com.hyj.spring.BeanNameAware;
    import com.hyj.spring.Component;
    import com.hyj.spring.Scope;
    
    @Component("userService")
    public class UserService implements BeanNameAware {
    
        @Autowired
        private OrderService orderService;
    
        private String beanName;
    
        public void printFiled() {
            System.out.println(orderService);
            System.out.println(beanName);
        }
    
        @Override
        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }
    }
    

    Spring容器createBean方法改造

        private Object createBean(String beanName, BeanDefinition beanDefinition) {
            Class clazz = beanDefinition.getClazz();
            Object beanObj = null;
            try {
                beanObj = clazz.getDeclaredConstructor().newInstance();
    
                // 依赖注入
                for (Field declaredField : clazz.getDeclaredFields()) {
                    if (declaredField.isAnnotationPresent(Autowired.class)) { //判断成员变量是否有@Autowired注解
                        Object fieldBean = getBean(declaredField.getName()); // 根据beanName获取对应bean
                        declaredField.setAccessible(true);
                        declaredField.set(beanObj, fieldBean);
                    }
                }
    
                //Aware回调
                if (beanObj instanceof BeanNameAware) {
                    ((BeanNameAware) beanObj).setBeanName(beanName);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return beanObj;
        }
    

    验证

    public class AppMain {
        public static void main(String[] args) {
            HyjApplicationContext applicationContext = new HyjApplicationContext(AppConfig.class);
    
            UserService userService = (UserService) applicationContext.getBean("userService");
            userService.printFiled();
        }
    }
    

    验证userService的属性beanName是否有值。

    四、手写Spring初始化机制

    Spring创建bean的最后完成bean初始化时会做一些事情,这里就涉及到spring的初始化技术。

    定义InitializingBean

    package com.hyj.spring;
    
    public interface InitializingBean {
        void afterPropertiesSet() throws Exception;
    }
    

    实现InitializingBean接口

    package com.hyj.test.service;
    
    import com.hyj.spring.*;
    
    @Component("userService")
    public class UserService implements BeanNameAware, InitializingBean {
    
        @Autowired
        private OrderService orderService;
    
        private String beanName;
    
        public void printFiled() {
            System.out.println(orderService);
            System.out.println(beanName);
        }
    
        @Override
        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            // 可以做一些初始化的工作 验证,赋值
            System.out.println("Bean初始化。。。");
        }
    }
    

    Spring容器createBean方法改造

        private Object createBean(String beanName, BeanDefinition beanDefinition) {
            Class clazz = beanDefinition.getClazz();
            Object beanObj = null;
            try {
                // 实例化
                beanObj = clazz.getDeclaredConstructor().newInstance();
    
                // 依赖注入
                for (Field declaredField : clazz.getDeclaredFields()) {
                    if (declaredField.isAnnotationPresent(Autowired.class)) { //判断成员变量是否有@Autowired注解
                        Object fieldBean = getBean(declaredField.getName()); // 根据beanName获取对应bean
                        declaredField.setAccessible(true);
                        declaredField.set(beanObj, fieldBean);
                    }
                }
    
                //Aware回调
                if (beanObj instanceof BeanNameAware) {
                    ((BeanNameAware) beanObj).setBeanName(beanName);
                }
    
                // 初始化
                if (beanObj instanceof InitializingBean) {
                    ((InitializingBean)beanObj).afterPropertiesSet();
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return beanObj;
        }
    

    验证

    public class AppMain {
        public static void main(String[] args) {
            HyjApplicationContext applicationContext = new HyjApplicationContext(AppConfig.class);
        }
    }
    

    五、手写Spring后置处理器BeanPostProcessor

    当在创建bean的各个时期做某些操作时,可以使用spring的后置处理器来解决,把处理的操作作为业务代码,只需要继承BeanPostProcessor接口就行,spring会在创建bean的指定的各个时期调用接口的方法。

    定义BeanPostProcessor接口

    package com.hyj.spring;
    
    public interface BeanPostProcessor {
    
        default Object postProcessBeforeInitialization(Object bean, String beanName) {
            return bean;
        }
    
        default Object postProcessAfterInitialization(Object bean, String beanName) {
            return bean;
        }
    }
    

    为验证这个处理器,可以在userService中新增一个message字段作为测试字段

    @Component("userService")
    public class UserService implements BeanNameAware, InitializingBean {
        @Autowired
        private OrderService orderService;
        private String beanName; // 为验证Aware回调
        private String message; // 为验证后置处理器BeanPostProcessor
    
        public void printFiled() {
            System.out.println(orderService);
            System.out.println(beanName);
            System.out.println(message);
        }
    
        @Override
        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            // 可以做一些初始化的工作 验证,赋值
            System.out.println("userService Bean初始化。。。");
        }
    }
    
    

    实现一个BeanPostProcessor的实现

    此时可以按照业务需要实现自己的BeanPostProcessor处理器。

    package com.hyj.test.service;
    
    import com.hyj.spring.BeanPostProcessor;
    import com.hyj.spring.Component;
    
    @Component("hjyBeanPostProcessor")
    public class HyjBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) {
            // 可以做某些处理
    
            System.out.println(beanName + "初始化前的操作。。。");
            if (beanName.equals("userService")) {//这里假设只对某个bean进行某些处理操作
                ((UserService)bean).setMessage("beanName : " + beanName + ", 调用了postProcessBeforeInitialization方法");
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            System.out.println(beanName + "初始化后的操作。。。");
            return bean;
        }
    }
    

    并且把这个后置处理器纳入spring的bean容器管理。

    那么,在spring扫描bean的时候,对BeanPostProcessor的这类的bean做特殊处理(先实例化然后暂存起来),以便后面createBean的各个时期来使用BeanPostProcessor来作为后置处理器处理一些额外的业务。

    在Spring容器类HyjApplicationContext类中改造对应方法:

        private void scanAndParseToBeanDefinitions(String packagePath) {
            URL resource = HyjApplicationContext.class.getClassLoader().getResource(packagePath);//使用App加载器获取资源文件URL
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File f : file.listFiles()) { //便利所有文件
                    String absolutePath = f.getAbsolutePath();
                    if (absolutePath.endsWith(".class")) {//只扫描class文件
                        String fullyQualifiedClassName = getFullyQualifiedClassName(absolutePath);
                        try {
                            Class<?> aClass = HyjApplicationContext.class.getClassLoader().loadClass(fullyQualifiedClassName);
                            // 这个类上有@Component注解,表示当前类应该是一个bean
                            if (aClass.isAnnotationPresent(Component.class)) {
                                // 需要在扫描的时候就实例化这个bean吗?这和这个bean的作用域有关系.
                                // 解析这个类,把类的定义信息解析额出来 ---> BeanDefinition
    
                                // 对BeanPostProcessor的所有bean进行特殊处理
                                if (BeanPostProcessor.class.isAssignableFrom(aClass)) {//这个类是否实现类类当前接口
                                    BeanPostProcessor instance = (BeanPostProcessor) aClass.getDeclaredConstructor().newInstance();
                                    beanPostProcessorList.add(instance);
                                }
    
                                parseClassToBeanDefinition(aClass);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    

    createBean时进行后置处理

    最后,就可以在创建bean的各个时期前后做加工处理,可以放在任何时期。

    这里就放在 初始化 的前后做相关操作。

    在Spring容器类HyjApplicationContext的createBean方法里改造:

        private Object createBean(String beanName, BeanDefinition beanDefinition) {
            Class clazz = beanDefinition.getClazz();
            Object beanObj = null;
            try {
                // 实例化
                beanObj = clazz.getDeclaredConstructor().newInstance();
    
                // 依赖注入
                for (Field declaredField : clazz.getDeclaredFields()) {
                    if (declaredField.isAnnotationPresent(Autowired.class)) { //判断成员变量是否有@Autowired注解
                        Object fieldBean = getBean(declaredField.getName()); // 根据beanName获取对应bean
                        declaredField.setAccessible(true);
                        declaredField.set(beanObj, fieldBean);
                    }
                }
    
                //Aware回调
                if (beanObj instanceof BeanNameAware) {
                    ((BeanNameAware) beanObj).setBeanName(beanName);
                }
    
                // 初始化前需要做的事,使用BeanPostProcessor处理
                // 这个地方可以定义各种类型的BeanPostProcessor
                for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                    beanObj = beanPostProcessor.postProcessBeforeInitialization(beanObj, beanName);
                }
    
                // 初始化
                if (beanObj instanceof InitializingBean) {
                    ((InitializingBean)beanObj).afterPropertiesSet();
                }
    
                // 初始化后需要做的事,使用BeanPostProcessor处理
                for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                    beanObj = beanPostProcessor.postProcessAfterInitialization(beanObj, beanName);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return beanObj;
        }
    

    验证

        public static void main(String[] args) {
            HyjApplicationContext applicationContext = new HyjApplicationContext(AppConfig.class);
    
            UserService userService = (UserService) applicationContext.getBean("userService");
            userService.printFiled();
        }
    

    打印如下:

    orderService初始化前的操作。。。
    orderService初始化后的操作。。。
    userService初始化前的操作。。。
    userService Bean初始化。。。
    userService初始化后的操作。。。
    hjyBeanPostProcessor初始化前的操作。。。
    hjyBeanPostProcessor初始化后的操作。。。
    com.hyj.test.service.OrderService@5451c3a8
    userService
    beanName : userService, 调用了postProcessBeforeInitialization方法
    

    六、手写Spring之AOP实现

    如果想在业务类UserService的方法printFiled上做AOP的,可以基于上一节中的BeanPostProcessor,在bean初始化后返回一个代理bean对象,那么userService再调用printFiled方法时就可以先执行代理加的操作,然后在执行原有操作。

    使用jdk的动态代理,需要一个接口

    package com.hyj.test.service;
    
    public interface UserInterface {
        public void printFiled();
    }
    

    UserService改造,仅继承上面接口:

    @Component("userService")
    //@Scope("prototype")
    public class UserService implements BeanNameAware, InitializingBean, UserInterface {
    
        @Autowired
        private OrderService orderService;
    
        private String beanName; // 为验证Aware回调
        private String message; // 为验证后置处理器BeanPostProcessor
    
        public void printFiled() {
            System.out.println(orderService);
            System.out.println(beanName);
            System.out.println(message);
        }
    
        @Override
        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            // 可以做一些初始化的工作 验证,赋值
            System.out.println("userService Bean初始化。。。");
        }
    }
    

    此文就不再新搞一个BeanPostProcessor了,还是用原来HyjBeanPostProcessor改造,在初始化后(postProcessAfterInitialization方法)用jdk代理生成一个代理对象返回。

    bean初始化后返回代理对象

    @Component("hjyBeanPostProcessor")
    public class HyjBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) {
            // 可以做某些处理
    
            System.out.println(beanName + "初始化前的操作。。。");
            if (beanName.equals("userService")) {//这里假设只对某个bean进行某些处理操作
                ((UserService)bean).setMessage("beanName : " + beanName + ", 调用了postProcessBeforeInitialization方法");
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            System.out.println(beanName + "初始化后的操作。。。");
    
            if ("userService".equals(beanName)) { // 仅对指定的bean进行代理
                Object proxyInstance = Proxy.newProxyInstance(HyjBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println(beanName + "执行代理逻辑before");
                        Object invoke = method.invoke(bean, args);
                        System.out.println(beanName + "执行代理逻辑after");
                        return invoke;
                    }
                });
                return proxyInstance;
            }
            return bean;
        }
    }
    

    验证

        public static void main(String[] args) {
            HyjApplicationContext applicationContext = new HyjApplicationContext(AppConfig.class);
    
    //        UserService userService = (UserService) applicationContext.getBean("userService");
    //        userService.printFiled();
    
            UserInterface userInterface = (UserInterface) applicationContext.getBean("userService");
            userInterface.printFiled();
        }
    

    打印结果:

    orderService初始化前的操作。。。
    orderService初始化后的操作。。。
    userService初始化前的操作。。。
    userService Bean初始化。。。
    userService初始化后的操作。。。
    hjyBeanPostProcessor初始化前的操作。。。
    hjyBeanPostProcessor初始化后的操作。。。
    【重点关注】userService执行代理逻辑before
    com.hyj.test.service.OrderService@2c7b84de
    userService
    beanName : userService, 调用了postProcessBeforeInitialization方法
    【重点关注】userService执行代理逻辑after
    

    相关文章

      网友评论

          本文标题:手写Spring之IOC和AOP的简易实现

          本文链接:https://www.haomeiwen.com/subject/qitqhrtx.html