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

2022-01-16  本文已影响0人  zhemehao819

仅供参考学习。

一、手写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;
    }
}

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

这时候需要一个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
上一篇下一篇

猜你喜欢

热点阅读