原创

Spring框架学习-基础


Spring框架学习-基础

1.Spring容器

import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.Controller;

/
 * 测试Spring中的ApplicationContext
 *
 * @author lzlg
 * 2023/3/8 17:56
 */
public class TestSpringApplicationContext {
    public static void main(String[] args) {
//        testClassPathXmlApplicationContext();
//        testFileSystemXmlApplicationContext();
//        testAnnotationConfigApplicationContext();

        testAnnotationConfigServletWebServerApplicationContext();
    }

    /
     * 文件系统路径下查找Bean的定义xml文件
     */
    private static void testFileSystemXmlApplicationContext() {
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("bean01.xml");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
        Bean2 bean2 = context.getBean(Bean2.class);
        System.out.println(bean2.getBean1());
    }

    /
     * 类路径下查找Bean的定义xml文件
     */
    private static void testClassPathXmlApplicationContext() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
        Bean2 bean2 = context.getBean(Bean2.class);
        System.out.println(bean2.getBean1());
    }

    /
     * 基于注解的ApplicationContext
     */
    private static void testAnnotationConfigApplicationContext() {
        // 需指定配置类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
        Bean2 bean2 = context.getBean(Bean2.class);
        System.out.println(bean2.getBean1());
    }

    /
     * 基于注解的在web环境使用的ApplicationContext
     */
    private static void testAnnotationConfigServletWebServerApplicationContext() {
        // 注意不是 AnnotationConfigServletWebApplicationContext
        // 必须是   AnnotationConfigServletWebServerApplicationContext
        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

    @Configuration
    static class WebConfig {
        // 注入内嵌的Tomcat Servlet容器
        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            return new TomcatServletWebServerFactory();
        }

        // Spring处理web请求的入口Servlet
        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        // 将内嵌的Tomcat Servlet容器和DispatcherServlet进行关联
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        // 向容器中注入controller处理/hello请求
        @Bean("/hello")
        public Controller helloController() {
            return (request, response) -> {
                response.getWriter().println("hello,world.");
                return null;
            };
        }

    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(Bean1 bean1) {
            Bean2 bean2 = new Bean2();
            bean2.setBean1(bean1);
            return bean2;
        }
    }

    static class Bean1 {

    }

    static class Bean2 {

        private Bean1 bean1;

        public void setBean1(Bean1 bean1) {
            this.bean1 = bean1;
        }

        public Bean1 getBean1() {
            return bean1;
        }
    }
}

2.BeanFactory

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.Map;

/
 * 测试Spring中的BeanFactory
 *
 * @author lzlg
 * 2023/3/5 19:33
 */
public class TestSpringBeanFactory {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 注入bean的定义信息(类是什么,scope范围是什么,初始化方法,销毁方法等)
        AbstractBeanDefinition configBeanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(Config.class)
                .setScope(ConfigurableBeanFactory.SCOPE_SINGLETON)
                .getBeanDefinition();
        beanFactory.registerBeanDefinition("config", configBeanDefinition);

        // 注入常见的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        // 注入后置处理器不会生效,需调用设置方法才能让后置处理器生效

        // 获取Bean工厂的后置处理器,可解析@Configuration注解和@Bean注解
        Map<String, BeanFactoryPostProcessor> factoryPostProcessorMap = beanFactory.getBeansOfType(
                BeanFactoryPostProcessor.class);
        // 使Bean工厂后置处理器在Bean工厂中生效
        factoryPostProcessorMap.values().forEach(beanFactoryPostProcessor ->
                beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));


        // 获取Bean的后置处理器,可解析@Autowired @Resource注解
        Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        // 将Bean的后置处理器放置在Bean工厂中生效
        beanPostProcessorMap.values().stream()
                // 可通过beanFactory.getDependencyComparator()来指定顺序
                // 处理@Autowired注解的处理器AutowiredAnnotationBeanPostProcessor默认比
                // 处理@Resource注解的处理器CommonAnnotationBeanPostProcessor在前面
//                .sorted(beanFactory.getDependencyComparator())
                .forEach(beanPostProcessor -> {
                    System.out.println("==========>>>>>>>" + beanPostProcessor);
                    beanFactory.addBeanPostProcessor(beanPostProcessor);
                });
//        Bean1 bean1 = beanFactory.getBean(Bean1.class);
//        System.out.println(bean1.getBean2());

        // BeanFactory的getBean方法是懒加载,当真正需要Bean时才进行创建,可通过下面方法提前实例化
        beanFactory.preInstantiateSingletons();

        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

        // @Autowired注解如果遇到两个实现接口的实例,如果字段名称匹配,则使用字段名称匹配的
        // @Resource注解通过指定bean名称进行匹配

        System.out.println(beanFactory.getBean(Bean1.class).getInter());

        // 当@Autowired和@Resource同时存在时,则看哪个bean的后置处理器在前面,以在前面的为准
        // 默认是@Autowired在前,因为其order为Ordered.LOWEST_PRECEDENCE - 2
        // 而@Resource注解的order为Ordered.LOWEST_PRECEDENCE - 3


        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 获取BeanFactory中定义的bean名称数组
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String beanName : beanDefinitionNames) {
            System.out.println(beanName);
        }
    }

    @Configuration
    static class Config {

        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }

        @Bean
        public Bean3 bean3() {
            return new Bean3();
        }

        @Bean
        public Bean4 bean4() {
            return new Bean4();
        }

    }

    interface Inter {

    }

    static class Bean3 implements Inter {

    }

    static class Bean4 implements Inter {

    }

    static class Bean1 {
        public Bean1() {
            System.out.println("Bean1() 构造...");
        }

        @Autowired
        public Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }

        // 当@Autowired和@Resource同时存在时
        @Autowired
        @Resource(name = "bean4")
        public Inter bean3;

        // 通过指定名称解决冲突
//        @Resource(name = "bean4")
//        public Inter bean3;

        // 通过指定字段名称解决冲突
//        @Autowired
//        public Inter bean3;

        public Inter getInter() {
            return bean3;
        }
    }

    static class Bean2 {
        public Bean2() {
            System.out.println("Bean2() 构造...");
        }
    }
}

3.Spring Bean的生命周期

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/
 * Spring中Bean的生命周期: 创建(构造), 依赖注入, 初始化, 销毁
 *
 * @author lzlg
 * 2023/3/8 19:19
 */
@Component("springBeanLifeCycle")
public class SpringBeanLifeCycle {

    public SpringBeanLifeCycle() {
        System.out.println("构造 SpringBeanLifeCycle");
    }

    @Autowired
    public void autowire(@Value("${JAVA_HOME}") String javaHome) {
        System.out.println("依赖注入: " + javaHome);
    }

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

    @PreDestroy
    public void destroy() {
        System.out.println("销毁...");
    }
}

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;

/
 * Spring中生命周期中的Bean后置处理器
 *
 * @author lzlg
 * 2023/3/8 19:26
 */
@Component
public class MyLifeCycleBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if (beanName.equals("springBeanLifeCycle")) {
            System.out.println(">>>>>> postProcessBeforeDestruction在Bean销毁之前调用,如@PreDestroy");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("springBeanLifeCycle")) {
            System.out.println(">>>>>> postProcessBeforeInstantiation在Bean实例化(构造)之前调用,此方法返回的Bean会替换原来的");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("springBeanLifeCycle")) {
            System.out.println(">>>>>> postProcessAfterInstantiation在Bean实例化(构造)之后调用,返回false则跳过依赖注入");
            return true;
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("springBeanLifeCycle")) {
            System.out.println(">>>>>> postProcessProperties在Bean依赖注入阶段执行,如@Autowired,@Value,@Resource");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("springBeanLifeCycle")) {
            System.out.println(">>>>>> postProcessBeforeInitialization在Bean初始化之前调用,此方法返回的Bean会替换原来的," +
                    "如@PostConstruct,@ConfigurationProperties");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("springBeanLifeCycle")) {
            System.out.println(">>>>>> postProcessAfterInitialization在Bean初始化之后调用,此方法返回的Bean会替换原来的," +
                    "如代理增强");
        }
        return bean;
    }
}

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/
 * 启动类
 *
 * @author lzlg
 * 2023/3/8 19:19
 */
@SpringBootApplication
public class SecondApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SecondApplication.class, args);
        context.close();
    }
}

4.Spring Bean后置处理器

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.support.GenericApplicationContext;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

/
 * 测试Spring中常见的Bean后置处理器
 *
 * @author lzlg
 * 2023/3/8 19:56
 */
public class TestSpringBeanPostProcessor {
    public static void main(String[] args) {
        // GenericApplicationContext容器比较干净
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        context.registerBean("bean4", Bean4.class);

        // 解析@Autowired和@Value注解的后置处理器
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        // 要解析@Value中的${}信息,还需向context中的beanFactory添加解析器
        context.getDefaultListableBeanFactory().setAutowireCandidateResolver(
                new ContextAnnotationAutowireCandidateResolver());

        // 解析@Resource,@PostConstruct,@PreDestroy注解的后置处理器
        context.registerBean(CommonAnnotationBeanPostProcessor.class);
        // 可以看到@Resource注解先于@Autowired进行解析,因为处理器的排序造成的
        // CommonAnnotationBeanPostProcessor的优先级是Ordered.LOWEST_PRECEDENCE - 3
        // AutowiredAnnotationBeanPostProcessor的优先级是Ordered.LOWEST_PRECEDENCE - 2
        // 数值越小的优先级越高


        // 解析Spring Boot中的注解@ConfigurationProperties
        ConfigurationPropertiesBindingPostProcessor.register(context);

        context.refresh();
        // 查看Bean4中绑定的属性解析了没有
        System.out.println(context.getBean(Bean4.class));


        context.close();
    }

    static class Bean1 {

        private Bean2 bean2;

        @Autowired
        public void setBean2(Bean2 bean2) {
            System.out.println("@Autowired 依赖注入... bean2");
            this.bean2 = bean2;
        }

        private String javaHome;

        @Autowired
        public void setJavaHome(@Value("${JAVA_HOME}") String javaHome) {
            System.out.println("@Value 依赖注入... " + javaHome);
            this.javaHome = javaHome;
        }

        private Bean3 bean3;

        @Resource
        public void setBean3(Bean3 bean3) {
            System.out.println("@Resource 依赖注入... bean3");
            this.bean3 = bean3;
        }

        @PostConstruct
        public void init() {
            System.out.println("@PostConstruct Bean1 初始化...");
        }

        @PreDestroy
        public void destroy() {
            System.out.println("@PreDestroy Bean1 销毁...");
        }
    }

    static class Bean2 {

    }

    static class Bean3 {

    }

    @ConfigurationProperties(prefix = "java")
    static class Bean4 {

        private String home;

        private String version;

        public String getHome() {
            return home;
        }

        public String getVersion() {
            return version;
        }

        public void setHome(String home) {
            this.home = home;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        @Override
        public String toString() {
            return "Bean4{" +
                    "home='" + home + '\'' +
                    ", version='" + version + '\'' +
                    '}';
        }
    }
}

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/
 * 测试Spring中解析@Autowired注解的Bean后置处理器
 *
 * @author lzlg
 * 2023/3/8 19:56
 */
public class TestAutowiredBeanPostProcessor {
    public static void main(String[] args) throws Throwable {
        // 使用BeanFactory进行测试
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 使用registerSingleton注入单例bean,new出的bean则是成品Bean,不会触发创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean2", new Bean2());
        beanFactory.registerSingleton("bean3", new Bean3());
        // 解析@Value注解的解析器
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 解析@Value中的${}表达式
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        // 添加@Autowired注解处理器
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        // 1.AutowiredAnnotationBeanPostProcessor中进行注入处理的方法是postProcessProperties
        Bean1 bean1 = new Bean1();
        processor.postProcessProperties(null, bean1, "bean1");
        System.out.println(bean1);

        // 2.postProcessProperties中进行依赖注入的有两个步骤
        // 第一个是private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz,
        // @Nullable PropertyValues pvs) 方法
        // 第二个是InjectionMetadata对象的public void inject(Object target, @Nullable String beanName,
        // @Nullable PropertyValues pvs) throws Throwable方法
        Method findAutowiringMetadataMethod = AutowiredAnnotationBeanPostProcessor.class
                .getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadataMethod.setAccessible(true);
        // 反射调用findAutowiringMetadata方法
        InjectionMetadata injectionMetadata = (InjectionMetadata) findAutowiringMetadataMethod
                .invoke(processor, "bean1", Bean1.class, null);
        // 进行依赖注入,注入时按照类型进行查找
        injectionMetadata.inject(bean1, "bean1", null);
        System.out.println(bean1);

        // 3.InjectionMetadata的依赖注入流程
        // 如果是字段上有@Autowired注解
        Field bean3Field = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor bean3DependencyDescriptor = new DependencyDescriptor(bean3Field, false);
        Object bean3 = beanFactory.doResolveDependency(bean3DependencyDescriptor, null, null, null);
        System.out.println(bean3);

        // 如果是方法上有@Autowired注解
        Method bean2Method = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor bean2DependencyDescriptor = new DependencyDescriptor(
                new MethodParameter(bean2Method, 0), true);
        Object bean2 = beanFactory.doResolveDependency(bean2DependencyDescriptor, null, null, null);
        System.out.println(bean2);

        // 如果方法上是@Value注入
        Method javaHomeMethod = Bean1.class.getDeclaredMethod("setJavaHome", String.class);
        DependencyDescriptor javaHomeDependencyDescriptor = new DependencyDescriptor(
                new MethodParameter(javaHomeMethod, 0), true);
        Object javaHome = beanFactory.doResolveDependency(javaHomeDependencyDescriptor, null, null, null);
        System.out.println(javaHome);

    }

    static class Bean1 {

        private Bean2 bean2;

        @Autowired
        public void setBean2(Bean2 bean2) {
            System.out.println("@Autowired 依赖注入... bean2");
            this.bean2 = bean2;
        }

        private String javaHome;

        @Autowired
        public void setJavaHome(@Value("${JAVA_HOME}") String javaHome) {
            System.out.println("@Value 依赖注入... " + javaHome);
            this.javaHome = javaHome;
        }

        @Autowired
        private Bean3 bean3;

        @Resource
        public void setBean3(Bean3 bean3) {
            System.out.println("@Resource 依赖注入... bean3");
            this.bean3 = bean3;
        }

        @PostConstruct
        public void init() {
            System.out.println("@PostConstruct Bean1 初始化...");
        }

        @PreDestroy
        public void destroy() {
            System.out.println("@PreDestroy Bean1 销毁...");
        }

        @Override
        public String toString() {
            return "Bean1{" +
                    "bean2=" + bean2 +
                    ", javaHome='" + javaHome + '\'' +
                    ", bean3=" + bean3 +
                    '}';
        }
    }

    static class Bean2 {

    }

    static class Bean3 {

    }
}

5.Spring BeanFactory后置处理器

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.Map;

/
 * 测试Spring中的BeanFactory
 *
 * @author lzlg
 * 2023/3/5 19:33
 */
public class TestSpringBeanFactory {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 注入bean的定义信息(类是什么,scope范围是什么,初始化方法,销毁方法等)
        AbstractBeanDefinition configBeanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(Config.class)
                .setScope(ConfigurableBeanFactory.SCOPE_SINGLETON)
                .getBeanDefinition();
        beanFactory.registerBeanDefinition("config", configBeanDefinition);

        // 注入常见的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        // 注入后置处理器不会生效,需调用设置方法才能让后置处理器生效

        // 获取Bean工厂的后置处理器,可解析@Configuration注解和@Bean注解
        Map<String, BeanFactoryPostProcessor> factoryPostProcessorMap = beanFactory.getBeansOfType(
                BeanFactoryPostProcessor.class);
        // 使Bean工厂后置处理器在Bean工厂中生效
        factoryPostProcessorMap.values().forEach(beanFactoryPostProcessor ->
                beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));


        // 获取Bean的后置处理器,可解析@Autowired @Resource注解
        Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        // 将Bean的后置处理器放置在Bean工厂中生效
        beanPostProcessorMap.values().stream()
                // 可通过beanFactory.getDependencyComparator()来指定顺序
                // 处理@Autowired注解的处理器AutowiredAnnotationBeanPostProcessor默认比
                // 处理@Resource注解的处理器CommonAnnotationBeanPostProcessor在前面
//                .sorted(beanFactory.getDependencyComparator())
                .forEach(beanPostProcessor -> {
                    System.out.println("==========>>>>>>>" + beanPostProcessor);
                    beanFactory.addBeanPostProcessor(beanPostProcessor);
                });
//        Bean1 bean1 = beanFactory.getBean(Bean1.class);
//        System.out.println(bean1.getBean2());

        // BeanFactory的getBean方法是懒加载,当真正需要Bean时才进行创建,可通过下面方法提前实例化
        beanFactory.preInstantiateSingletons();

        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

        // @Autowired注解如果遇到两个实现接口的实例,如果字段名称匹配,则使用字段名称匹配的
        // @Resource注解通过指定bean名称进行匹配

        System.out.println(beanFactory.getBean(Bean1.class).getInter());

        // 当@Autowired和@Resource同时存在时,则看哪个bean的后置处理器在前面,以在前面的为准
        // 默认是@Autowired在前,因为其order为Ordered.LOWEST_PRECEDENCE - 2
        // 而@Resource注解的order为Ordered.LOWEST_PRECEDENCE - 3


        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 获取BeanFactory中定义的bean名称数组
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String beanName : beanDefinitionNames) {
            System.out.println(beanName);
        }
    }

    @Configuration
    static class Config {

        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }

        @Bean
        public Bean3 bean3() {
            return new Bean3();
        }

        @Bean
        public Bean4 bean4() {
            return new Bean4();
        }

    }

    interface Inter {

    }

    static class Bean3 implements Inter {

    }

    static class Bean4 implements Inter {

    }

    static class Bean1 {
        public Bean1() {
            System.out.println("Bean1() 构造...");
        }

        @Autowired
        public Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }

        // 当@Autowired和@Resource同时存在时
        @Autowired
        @Resource(name = "bean4")
        public Inter bean3;

        // 通过指定名称解决冲突
//        @Resource(name = "bean4")
//        public Inter bean3;

        // 通过指定字段名称解决冲突
//        @Autowired
//        public Inter bean3;

        public Inter getInter() {
            return bean3;
        }
    }

    static class Bean2 {
        public Bean2() {
            System.out.println("Bean2() 构造...");
        }
    }
}

import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

/
 * 测试常见的Bean工厂后置处理器
 *
 * @author lzlg
 * 2023/3/9 18:25
 */
public class TestBeanFactoryPostProcessor {
    public static void main(String[] args) throws Exception {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config", Config.class);
        // 注入自己编写的bean工厂后置处理器
//        context.registerBean(MyComponentScanPostProcessor.class);

        // 解析@Bean注解
        context.registerBean(MyAtBeanPostProcessor.class);
        // 解析Mapper接口
        context.registerBean(MyMapperPostProcessor.class);

        context.refresh();
        System.out.println(">>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<");
        // 打印容器中的bean名称
        String[] definitionNames = context.getBeanDefinitionNames();
        for (String definitionName : definitionNames) {
            System.out.println(definitionName);
        }
        context.close();
    }

    /
     * 测试常见的Bean工厂后置处理器
     */
    private static void testBeanFactoryPostProcessor() {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config", Config.class);
        // 如需配置类生效,需注入ConfigurationClassPostProcessor这个处理器
        // 会解析@ComponentScan @Bean @Import @ImportResource
        context.registerBean(ConfigurationClassPostProcessor.class);

        // mybatis中使用的扫描包的bean工厂后置处理器MapperScannerConfigurer
        // 但需指定扫描的包信息
        context.registerBean(MapperScannerConfigurer.class, bd -> {
            bd.getPropertyValues().add("basePackage", "com.lzlg.study.spring.third.mapper");
        });

        context.refresh();
        // 打印容器中的bean名称
        String[] definitionNames = context.getBeanDefinitionNames();
        for (String definitionName : definitionNames) {
            System.out.println(definitionName);
        }
        context.close();
    }
}

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;

/
 * 自定义实现@ComponentScan注解功能的Bean工厂后置处理器
 *
 * @author lzlg
 * 2023/3/9 19:14
 */
public class MyComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // >>>>>自己实现Bean工厂后置处理器的逻辑<<<<<
        // 查看配置类中是否有ComponentScan注解
        ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
        // 如果有
        try {
            if (componentScan != null) {
                // 获取注解上的包名信息
                String[] basePackages = componentScan.basePackages();
                for (String basePackage : basePackages) {
                    // System.out.println(basePackage);
                    // 将包名转换为类路径下的class文件存放路径
                    // com.lzlg.study.spring.third.component 变为
                    // classpath*:com/lzlg/study/spring/third/component//*.class
                    String classpath = "classpath*:" + basePackage.replace(".", "/") + "//*.class";
                    // System.out.println(classpath);
                    // 根据路径使用CachingMetadataReaderFactory进行读取
                    CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
                    // 获取类路径下的资源
                    Resource[] resources = new PathMatchingResourcePatternResolver().getResources(classpath);
                    // 通过注解生成Bean名称
                    AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
                    // Bean2是加了@Component注解的,Bean3是@Service注解(属于@Component的派生注解)
                    // Bean4无任何注解
                    for (Resource resource : resources) {
                        // System.out.println(resource);
                        // System.out.println(">>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<");
                        // 读取类的元信息
                        MetadataReader metadataReader = readerFactory.getMetadataReader(resource);
                        // Bean的类名
                        String beanClassName = metadataReader.getClassMetadata().getClassName();
                        // 注解元信息
                        AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
                        // System.out.println("类名是: " + beanClassName);
                        // System.out.println("是否加了@Component注解: " +
                        //        metadata.hasAnnotation(Component.class.getName()));
                        // System.out.println("是否加了@Component的派生注解: " +
                        //        metadata.hasMetaAnnotation(Component.class.getName()));

                        // 如果有@Component注解和其派生注解
                        if (metadata.hasAnnotation(Component.class.getName())
                                || metadata.hasMetaAnnotation(Component.class.getName())) {
                            // 创建Bean定义信息
                            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                                    .genericBeanDefinition(beanClassName).getBeanDefinition();
                            // 生成Bean名称
                            String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
                            // 注册进Bean工厂中
                            registry.registerBeanDefinition(beanName, beanDefinition);
                        }
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
}

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/
 * 自定义解析@Bean注解的后置工厂处理器
 *
 * @author lzlg
 * 2023/3/9 19:46
 */
public class MyAtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // >>>>>>>>>>>自己编写解析@Bean注解的Bean工厂后置处理器<<<<<<<<<<<<
        // 读取元信息的工厂
        CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
        // 读取配置类的元信息
        MetadataReader metadataReader;
        try {
            metadataReader = readerFactory.getMetadataReader(
                    new ClassPathResource("com/lzlg/study/spring/postprocessor/Config.class"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 获取被@Bean注解标注的方法,没有@Bean注解的方法则不会解析
        Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata()
                .getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata method : annotatedMethods) {
            // System.out.println(method);

            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
            // 指定工厂方法,且是哪个Bean实例(配置类)的方法
            builder.setFactoryMethodOnBean(method.getMethodName(), "config");
            // 工厂方法和构造注入都是使用AUTOWIRE_CONSTRUCTOR这种类型的装配模式
            builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);

            // 获取方法上@Bean注解指定的初始化方法
            Object initMethodObj = Objects.requireNonNull(method.getAnnotationAttributes(Bean.class.getName()))
                    .get("initMethod");
            if (initMethodObj != null) {
                String initMethod = String.valueOf(initMethodObj);
                // 设置初始化方法
                builder.setInitMethodName(initMethod);
            }

            // 注入bean工厂中,bean名称是方法名称
            registry.registerBeanDefinition(method.getMethodName(), builder.getBeanDefinition());
        }

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Map<String, Object> beansWithAnnotation = beanFactory.getBeansWithAnnotation(Configuration.class);
        for (Map.Entry<String, Object> entry : beansWithAnnotation.entrySet()) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(entry.getKey());
        }
    }
}

import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;

/
 * 自定义Mapper接口Bean工厂后置处理器
 *
 * @author lzlg
 * 2023/3/9 20:16
 */
public class MyMapperPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        try {
            // 获取类路径下的Mapper接口class资源
            Resource[] resources = new PathMatchingResourcePatternResolver()
                    .getResources("com/lzlg/study/spring/postprocessor/mapper//*.class");
            // 元信息读取工厂
            CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
            // 通过注解获取bean名称的生成器
            AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
            for (Resource resource : resources) {
                // 获取元信息读取器
                MetadataReader reader = readerFactory.getMetadataReader(resource);
                // 有@Mapper注解的才进行处理
                if (reader.getAnnotationMetadata().hasAnnotation(Mapper.class.getName())) {
                    // 获取类的元信息
                    ClassMetadata classMetadata = reader.getClassMetadata();
                    // 类必须是接口才进行处理
                    if (classMetadata.isInterface()) {
                        // 创建MapperFactoryBean的BeanDefinition信息
                        AbstractBeanDefinition mapperFactoryBeanDefinition = BeanDefinitionBuilder
                                .genericBeanDefinition(MapperFactoryBean.class)
                                // MapperFactoryBean<Mapper1> factoryBean = new MapperFactoryBean<>(Mapper1.class);
                                // factoryBean.setSqlSessionFactory(sqlSessionFactory);
                                // return factoryBean;
                                .addConstructorArgValue(classMetadata.getClassName())
                                // 通过类查找到sqlSessionFactory
                                .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                                .getBeanDefinition();

                        // bean名称应该是Mapper接口实例bean的名称,而不是mapperFactoryBeanDefinition的名称
                        // 再次定义一个Mapper接口实例的Bean定义信息,专门用来生成Bean名称
                        AbstractBeanDefinition mapperBeanDefinition = BeanDefinitionBuilder
                                .genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();
                        // 生成Bean名称
                        String beanName = beanNameGenerator.generateBeanName(mapperBeanDefinition, registry);
                        // 注意要用mapperFactoryBeanDefinition,也就是工厂bean定义信息
                        registry.registerBeanDefinition(beanName, mapperFactoryBeanDefinition);

                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

import com.alibaba.druid.pool.DruidDataSource;
import com.lzlg.study.spring.postprocessor.component.Bean4;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/
 * 配置类
 *
 * @author lzlg
 * 2023/3/9 18:26
 */
@ComponentScan("com.lzlg.study.spring.postprocessor.component")
@Configuration
public class Config {

    public Bean4 bean4() {
        return new Bean4();
    }

    @Bean
    public Bean1 bean1() {
        return new Bean1();
    }

    @Bean(initMethod = "init")
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUsername("root");
        dataSource.setPassword("lzlg520!QAZ@WSX");
        return dataSource;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean;
    }

    /
     * Spring中是通过注入MapperFactoryBean<T>实现创建Mapper接口的Bean实例
     */
//    @Bean
//    public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory) {
//        MapperFactoryBean<Mapper1> factoryBean = new MapperFactoryBean<>(Mapper1.class);
//        factoryBean.setSqlSessionFactory(sqlSessionFactory);
//        return factoryBean;
//    }
//
//    @Bean
//    public MapperFactoryBean<Mapper2> mapper2(SqlSessionFactory sqlSessionFactory) {
//        MapperFactoryBean<Mapper2> factoryBean = new MapperFactoryBean<>(Mapper2.class);
//        factoryBean.setSqlSessionFactory(sqlSessionFactory);
//        return factoryBean;
//    }
}

6.Spring Aware接口

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.PostConstruct;

/
 * 测试Spring内置功能接口
 *
 * @author lzlg
 * 2023/3/9 21:02
 */
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {

    @Override
    public void setBeanName(String name) {
        System.out.println("当前bean: " + this + " 名字是: " + name);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("当前bean: " + this + " InitializingBean接口初始化方法afterPropertiesSet()");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("当前bean: " + this + " 容器是: " + applicationContext);
    }

    @PostConstruct
    public void init() {
        System.out.println("当前bean: " + this + " @PostConstruct初始化,方法init()");
    }
}

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/
 * 失效的初始化配置
 *
 * @author lzlg
 * 2023/3/9 21:08
 */
@Configuration
public class MyEffectConfig implements ApplicationContextAware, InitializingBean {

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        System.out.println(MyEffectConfig.class.getName() + " 注入 ApplicationContext");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(MyNoEffectConfig.class.getName() + " 初始化");
    }

    @Bean
    public BeanFactoryPostProcessor myEffectProcessor() {
        return beanFactory -> {
            System.out.println("执行 myEffectProcessor");
        };
    }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/
 * 失效的初始化配置
 *
 * @author lzlg
 * 2023/3/9 21:08
 */
@Configuration
public class MyNoEffectConfig {

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        System.out.println(MyNoEffectConfig.class.getName() + " 注入 ApplicationContext");
    }

    @PostConstruct
    public void init() {
        System.out.println(MyNoEffectConfig.class.getName() + " 初始化");
    }

    @Bean
    public BeanFactoryPostProcessor myNoEffectProcessor() {
        return beanFactory -> {
            System.out.println("执行 myNoEffectProcessor");
        };
    }
}

import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

/
 * @author lzlg
 * 2023/3/9 21:05
 */
public class TestSpring {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        // context.registerBean("myBean", MyBean.class);
        // context.registerBean("myNoEffectConfig", MyNoEffectConfig.class);
        // 通过实现Aware和InitializingBean相关接口,配置类中定义的后置处理器不会干扰到配置类的初始化
        context.registerBean("myEffectConfig", MyEffectConfig.class);
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        context.registerBean(CommonAnnotationBeanPostProcessor.class);
        context.registerBean(ConfigurationClassPostProcessor.class);
        context.refresh();
        context.close();
    }
}

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/
 * 测试Spring使用FactoryBean
 *
 * @author lzlg
 * 2023/4/8 21:33
 */
public class TestSpringFactoryBean {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBeanConfig.class);

        Object bean1 = context.getBean("bean");
        System.out.println(bean1);
        Object bean2 = context.getBean("bean");
        System.out.println(bean2);
        Object bean3 = context.getBean("bean");
        System.out.println(bean3);

        System.out.println(">>>>>>>>>>>>>>>>>>>>获取FactoryBean的方式: ");
        System.out.println(context.getBean(MyBeanFactory.class));
        System.out.println(context.getBean("&bean"));
        // 被FactoryBean创建的产品
        // 会认为创建,依赖注入,Aware接口回调,初始化前这些都是FactoryBean的职责,这些流程都不会走
        // 唯有后初始化的流程会走,也就是产品可以被代理增强
        //
        // 单例的产品不会存储于BeanFactory的singletonObjects(单例池)成员中,而是另一个factoryBeanObjectCache成员中
        // 按名字去获取时,拿到的是产品对象,名字前面加 & 获取的是工厂对象
    }
}

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/
 * 对于FactoryBean,只在初始化后可进行增强,故可对FactoryBean进行代理增强
 *
 * @author lzlg
 * 2023/4/8 21:38
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    /
     * 初始化前
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("bean") && bean instanceof MyBean) {
            System.out.println("MyBeanPostProcessor, postProcessBeforeInitialization...");
        }
        return bean;
    }

    /
     * 初始化后
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("bean") && bean instanceof MyBean) {
            System.out.println("MyBeanPostProcessor, postProcessAfterInitialization...");
        }
        return bean;
    }
}

import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;

/
 * @author lzlg
 * 2023/4/8 21:36
 */
@Component("bean")
public class MyBeanFactory implements FactoryBean<MyBean> {

    @Override
    public MyBean getObject() throws Exception {
        MyBean bean = new MyBean();
        System.out.println("factory create bean...");
        return bean;
    }

    /
     * 决定了getObject()方法被调用一次还是多次
     * 是单例则只调用一次
     */
    @Override
    public boolean isSingleton() {
        return true;
    }

    /
     * 返回Bean的类,这样可通过类型获取Bean
     */
    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }
}

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/
 * @author lzlg
 * 2023/4/8 21:34
 */
@Configuration
@ComponentScan
public class MyBeanConfig {
}

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;

/
 * @author lzlg
 * 2023/4/8 21:34
 */
public class MyBean implements BeanFactoryAware {

    private InjectBean bean;

    @Autowired
    public void setBean(InjectBean bean) {
        System.out.println("MyBean @Autowired...");
        this.bean = bean;
    }

    public InjectBean getBean() {
        return bean;
    }

    @PostConstruct
    public void init() {
        System.out.println("MyBean init()...");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("MyBean SetBeanFactory...");
    }
}

import org.springframework.stereotype.Component;

/
 * @author lzlg
 * 2023/4/8 21:34
 */
@Component
public class InjectBean {
}

7.Spring Bean的初始化和销毁

import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;

/
 * @author lzlg
 * 2023/3/9 21:19
 */
public class MyInitBean implements InitializingBean {

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

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean接口 初始化");
    }

    public void initMethod() {
        System.out.println("调用@Bean中的initMethod方法");
    }
}

import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;

/
 * 测试初始化Bean的执行顺序
 * 注解@PostConstruct > InitializingBean > @Bean中的initMethod
 * ===========================================================
 * 测试销毁Bean的执行顺序
 * 注解@Bean中的destroyMethod > 注解@PreDestroy > DisposableBean
 *
 * @author lzlg
 * 2023/3/9 21:16
 */
public class TestInitDestroyOrder {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
        context.registerBean(MyConfig.class);
        context.refresh();
        context.close();
    }

    @Configuration
    static class MyConfig {

        @Bean(initMethod = "initMethod")
        public MyInitBean myInitBean() {
            return new MyInitBean();
        }

        @Bean(initMethod = "destroyMethod")
        public MyDestroyBean myDestroyBean() {
            return new MyDestroyBean();
        }
    }

}

import org.springframework.beans.factory.DisposableBean;

import javax.annotation.PreDestroy;

/
 * @author lzlg
 * 2023/3/9 21:19
 */
public class MyDestroyBean implements DisposableBean {

    @PreDestroy
    public void beforeDestroy() {
        System.out.println("@PreDestroy 销毁");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean 销毁");
    }

    public void destroyMethod() {
        System.out.println("@Bean中定义的destroyMethod方法");
    }
}

8.Spring Bean的Scope

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

/
 * application的scope
 *
 * @author lzlg
 * 2023/3/10 18:47
 */
@Scope("application")
@Component
public class BeanForApplication {
    @PreDestroy
    public void destroy() {
        System.out.println("BeanForApplication destroy...");
    }
}

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

/
 * request的scope
 *
 * @author lzlg
 * 2023/3/10 18:47
 */
@Scope("request")
@Component
public class BeanForRequest {
    @PreDestroy
    public void destroy() {
        System.out.println("BeanForRequest destroy...");
    }
}

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

/
 * session的scope
 *
 * @author lzlg
 * 2023/3/10 18:47
 */
@Scope("session")
@Component
public class BeanForSession {
    @PreDestroy
    public void destroy() {
        System.out.println("BeanForSession destroy...");
    }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/
 * @author lzlg
 * 2023/3/10 18:49
 */
@RestController
public class MyScopeController {
    // 在request,session,application scope的bean在单例Bean中(MyScopeController)
    // 进行注入需要使用@Lazy生成代理
    @Lazy
    @Autowired
    private BeanForRequest beanForRequest;

    @Lazy
    @Autowired
    private BeanForSession beanForSession;

    @Lazy
    @Autowired
    private BeanForApplication beanForApplication;

    @GetMapping("/test")
    public String test(HttpServletRequest request, HttpSession session) {
        return "<ol>\n" +
                "    <li>BeanForRequest: " + beanForRequest + "</li>\n" +
                "    <li>BeanForSession: " + beanForSession + "</li>\n" +
                "    <li>BeanForApplication: " + beanForApplication + "</li>\n" +
                "</ol>";
    }
}

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/
 * 测试Spring中scope
 * 共有5种scope: singleton, prototype, request, session, application
 *
 * @author lzlg
 * 2023/3/10 18:45
 */
@SpringBootApplication
public class SixthApplication {
    public static void main(String[] args) {
        SpringApplication.run(SixthApplication.class, args);
    }
}

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/
 * 单例Bean注入prototype的scope的bean失效问题
 *
 * @author lzlg
 * 2023/3/10 19:06
 */
@Component
public class E {

    @Lazy
    @Autowired
    private F1 f1;

    public F1 getF1() {
        return f1;
    }

    @Autowired
    private F2 f2;

    public F2 getF2() {
        return f2;
    }

    @Autowired
    private ObjectFactory<F3> f3;

    public F3 getF3() {
        return f3.getObject();
    }

    @Autowired
    private ApplicationContext context;

    public F4 getF4() {
        return context.getBean(F4.class);
    }
}

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/
 * @author lzlg
 * 2023/3/10 19:07
 */
@ComponentScan("com.lzlg.study.spring.scope")
public class TestScopeApp {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestScopeApp.class);
        E e = context.getBean(E.class);
        // 单例Bean(这里是E)注入多例Bean(是F1)时
        // 单例Bean进行依赖注入时只会进行一次,所以每次get时都返回同一个bean
        // 解决方法一: 使用@Lazy注解,会创建注入的Bean的代理对象,延迟了多例Bean的创建
        System.out.println(e.getF1().getClass());
        System.out.println(e.getF1());
        System.out.println(e.getF1());
        System.out.println(e.getF1());
        System.out.println("===========================================");
        // 解决方法二: 在多例bean的@Scope注解的proxyMode属性改为ScopedProxyMode=TARGET_CLASS
        System.out.println(e.getF2().getClass());
        System.out.println(e.getF2());
        System.out.println(e.getF2());
        System.out.println(e.getF2());
        System.out.println("===========================================");
        // 解决方法三: 注入ObjectFactory<T>工厂bean
        System.out.println(e.getF3().getClass());
        System.out.println(e.getF3());
        System.out.println(e.getF3());
        System.out.println(e.getF3());
        System.out.println("===========================================");
        // 解决方法四: 使用ApplicationContext容器获取多例bean
        System.out.println(e.getF4().getClass());
        System.out.println(e.getF4());
        System.out.println(e.getF4());
        System.out.println(e.getF4());
        System.out.println("===========================================");
    }
}

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/
 * prototype的scope bean
 *
 * @author lzlg
 * 2023/3/10 19:08
 */
@Component
@Scope("prototype")
public class F1 {

}

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

/
 * prototype的scope bean
 *
 * @author lzlg
 * 2023/3/10 19:08
 */
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class F2 {

}

/
 * prototype的scope bean
 *
 * @author lzlg
 * 2023/3/10 19:08
 */
@Component
@Scope("prototype")
public class F3 {

}

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/
 * prototype的scope bean
 *
 * @author lzlg
 * 2023/3/10 19:08
 */
@Component
@Scope("prototype")
public class F4 {

}

9.Spring的AOP

1)AOP实现: AJC编译器和Agent类加载

需配置编译插件

    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.14.0</version>
                <configuration>
                    <complianceLevel>1.8</complianceLevel>
                    <source>8</source>
                    <target>8</target>
                    <showWeaveInfo>true</showWeaveInfo>
                    <verbose>true</verbose>
                    <Xlint>ignore</Xlint>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <!-- use this goal to weave all your main classes -->
                            <goal>compile</goal>
                            <!-- use this goal to weave all your test classes -->
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

测试代码:

import org.springframework.stereotype.Service;

/
 * 要增强的Service
 *
 * @author lzlg
 * 2023/3/10 19:29
 */
@Service
public class MyService {

    public void foo() {
        System.out.println("MyService foo()...");
    }

    public static void handle() {
        System.out.println("MyService static handle()...");
    }
}

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/
 * @author lzlg
 * 2023/3/10 19:32
 */
@Aspect
public class MyServiceAop {

    @Before("execution(* com.lzlg.study.spring.aop.MyService.foo())")
    public void before() {
        System.out.println("MyServiceAop before()...");
    }

    @After("execution(* com.lzlg.study.spring.aop.MyService.handle())")
    public void after() {
        System.out.println("MyServiceAop before()...");
    }
}

/
 * @author lzlg
 * 2023/3/10 19:33
 */
public class TestAspectAop {
    public static void main(String[] args) {
        // 通过AspectJ在[编译阶段]修改字节码来实现AOP
        // 这样可代理static静态方法和final方法
        new MyService().foo();
        MyService.handle();

        // 通过AspectJ-weaver在[类加载阶段]修改字节码来实现AOP
        // 这样也可以代理static静态方法和final方法
    }
}

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;

/
 * @author lzlg
 * 2023/3/10 21:30
 */
public class TestAsmBytecode {
    public static void main(String[] args) throws Exception {
        // 有了字节码,可以通过类加载到生成的代理对象的代码
        byte[] dump = $Proxy0Dump.dump();

//        FileOutputStream fos =new FileOutputStream("$Proxy0.class");
//        fos.write(dump, 0, dump.length);
//        fos.close();

        ClassLoader loader = new ClassLoader() {
            @Override
            protected Class<?> findClass(String name) throws ClassNotFoundException {
                return super.defineClass(name, dump, 0, dump.length);
            }
        };
        Class<?> proxyClass = loader.loadClass("com.lzlg.study.spring.proxy.asm.$Proxy0");
        Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
        // 利用构造器创建实例
        Foo proxyFoo = (Foo) constructor.newInstance((InvocationHandler) (proxy, method, arguments) -> {
            System.out.println("before....");
            Object result = null;
            System.out.println("after....");
            return result;
        });
        proxyFoo.foo();
    }
}

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

/
 * 自己实现JDK动态代理
 *
 * @author lzlg
 * 2023/3/10 21:08
 */
public class $Proxy0Template extends Proxy implements Foo {

    protected $Proxy0Template(InvocationHandler h) {
        super(h);
    }

    @Override
    public void foo() {
        try {
            this.h.invoke(this, foo, new Object[0]);
            return;
            // 运行时的异常进行处理
        } catch (RuntimeException | Error e) {
            throw e;
            // 其他异常,转换为UndeclaredThrowableException抛出
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    // 把方法转换为静态成员遍历,不用每次调用都反射生成
    static Method foo;

    static {
        try {
            foo = Foo.class.getMethod("foo");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }
}

/
 * 接口
 *
 * @author lzlg
 * 2023/3/10 21:07
 */
public interface Foo {

    void foo();
}

import org.springframework.asm.*;

/
 * @author lzlg
 * 2023/3/10 21:56
 */
public class $Proxy0Dump implements Opcodes {

    public static byte[] dump() throws Exception {

        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(52, ACC_PUBLIC + ACC_SUPER, "com/lzlg/study/spring/proxy/asm/$Proxy0", null, "java/lang/reflect/Proxy", new String[]{"com/lzlg/study/spring/proxy/asm/Foo"});

        cw.visitSource("$Proxy0.java", null);

        {
            fv = cw.visitField(ACC_STATIC, "foo", "Ljava/lang/reflect/Method;", null, null);
            fv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/reflect/InvocationHandler;)V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(11, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/Proxy", "<init>", "(Ljava/lang/reflect/InvocationHandler;)V", false);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLineNumber(12, l1);
            mv.visitInsn(RETURN);
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitLocalVariable("this", "Lcom/lzlg/study/spring/proxy/asm/$Proxy0;", null, l0, l2, 0);
            mv.visitLocalVariable("h", "Ljava/lang/reflect/InvocationHandler;", null, l0, l2, 1);
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "foo", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            Label l1 = new Label();
            Label l2 = new Label();
            mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
            mv.visitLabel(l0);
            mv.visitLineNumber(17, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, "com/lzlg/study/spring/proxy/asm/$Proxy0", "h", "Ljava/lang/reflect/InvocationHandler;");
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETSTATIC, "com/lzlg/study/spring/proxy/asm/$Proxy0", "foo", "Ljava/lang/reflect/Method;");
            mv.visitInsn(ACONST_NULL);
            mv.visitMethodInsn(INVOKEINTERFACE, "java/lang/reflect/InvocationHandler", "invoke", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true);
            mv.visitInsn(POP);
            mv.visitLabel(l1);
            mv.visitLineNumber(20, l1);
            Label l3 = new Label();
            mv.visitJumpInsn(GOTO, l3);
            mv.visitLabel(l2);
            mv.visitLineNumber(18, l2);
            mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/Throwable"});
            mv.visitVarInsn(ASTORE, 1);
            Label l4 = new Label();
            mv.visitLabel(l4);
            mv.visitLineNumber(19, l4);
            mv.visitTypeInsn(NEW, "java/lang/reflect/UndeclaredThrowableException");
            mv.visitInsn(DUP);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>", "(Ljava/lang/Throwable;)V", false);
            mv.visitInsn(ATHROW);
            mv.visitLabel(l3);
            mv.visitLineNumber(21, l3);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
            mv.visitInsn(RETURN);
            Label l5 = new Label();
            mv.visitLabel(l5);
            mv.visitLocalVariable("e", "Ljava/lang/Throwable;", null, l4, l3, 1);
            mv.visitLocalVariable("this", "Lcom/lzlg/study/spring/proxy/asm/$Proxy0;", null, l0, l5, 0);
            mv.visitMaxs(4, 2);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            Label l1 = new Label();
            Label l2 = new Label();
            mv.visitTryCatchBlock(l0, l1, l2, "java/lang/NoSuchMethodException");
            mv.visitLabel(l0);
            mv.visitLineNumber(26, l0);
            mv.visitLdcInsn(Type.getType("Lcom/lzlg/study/spring/proxy/asm/Foo;"));
            mv.visitLdcInsn("foo");
            mv.visitInsn(ICONST_0);
            mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false);
            mv.visitFieldInsn(PUTSTATIC, "com/lzlg/study/spring/proxy/asm/$Proxy0", "foo", "Ljava/lang/reflect/Method;");
            mv.visitLabel(l1);
            mv.visitLineNumber(29, l1);
            Label l3 = new Label();
            mv.visitJumpInsn(GOTO, l3);
            mv.visitLabel(l2);
            mv.visitLineNumber(27, l2);
            mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/NoSuchMethodException"});
            mv.visitVarInsn(ASTORE, 0);
            Label l4 = new Label();
            mv.visitLabel(l4);
            mv.visitLineNumber(28, l4);
            mv.visitTypeInsn(NEW, "java/lang/NoSuchMethodError");
            mv.visitInsn(DUP);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "getMessage", "()Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/NoSuchMethodError", "<init>", "(Ljava/lang/String;)V", false);
            mv.visitInsn(ATHROW);
            mv.visitLabel(l3);
            mv.visitLineNumber(30, l3);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
            mv.visitInsn(RETURN);
            mv.visitLocalVariable("e", "Ljava/lang/NoSuchMethodException;", null, l4, l3, 0);
            mv.visitMaxs(3, 1);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }
}

2)AOP实现: 代理Proxy

import java.io.IOException;
import java.lang.reflect.Proxy;

/
 * JDK动态代理,目前只能代理接口
 *
 * @author lzlg
 * 2023/3/10 20:09
 */
public class JdkProxyDemo {

    interface Foo {
        void foo();
    }

    static class Target implements Foo {

        @Override
        public void foo() {
            System.out.println("target foo()...");
        }
    }

    public static void main(String[] args) {
        // 创建代理目标对象
        Target target = new Target();
        // 生成代理实例
        Foo proxy = (Foo) Proxy.newProxyInstance(JdkProxyDemo.class.getClassLoader(),
                new Class[]{Foo.class}, (p, method, args1) -> {
                    System.out.println("before...");
                    Object result = method.invoke(target, args);
                    System.out.println("after...");
                    return result;
                });
        proxy.foo();
        System.out.println(proxy.getClass());

        try {
            System.in.read();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/
 * CGLIB代理
 *
 * @author lzlg
 * 2023/3/10 20:21
 */
public class CglibProxyDemo {

    static class Target {
        public void foo() {
            System.out.println("target foo()...");
        }
    }

    public static void main(String[] args) {
        // 代理目标,Target不能是final类,否则生成不了代理的子类
        Target target = new Target();

        // 创建代理
        Target proxy = (Target) Enhancer.create(Target.class, new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("before...");
                // Object result = method.invoke(target, args);// 使用反射调用,需要目标对象
                // Object result = methodProxy.invoke(target, args);// 非反射调用,需要目标对象,Spring中使用的
                Object result = methodProxy.invokeSuper(proxy, args);// 非反射调用,无须目标对象
                System.out.println("after...");
                return result;
            }
        });
        // 代理的方法不能是final方法,否则只会调用目标对象中的方法
        proxy.foo();
    }
}

自己模拟实现JDK和CGLIB的动态代理:

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/
 * 测试
 *
 * @author lzlg
 * 2023/3/11 18:22
 */
public class CglibProxyTest {
    public static void main(String[] args) {
        // 代理目标对象
        Target target = new Target();

        Proxy proxy = new Proxy();
        proxy.setMethodInterceptor(new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("before...");
                // 反射调用,需要目标对象
                // return method.invoke(target, args);
                // 非反射调用,使用MethodProxy,需要目标对象
                // return methodProxy.invoke(target, args);
                // 非反射调用,使用MethodProxy,需要代理对象
                return methodProxy.invokeSuper(proxy, args);
            }
        });

        proxy.save();
        proxy.save(1);
        proxy.save(2L);
    }
}

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

/
 * 代理对象是代理目标的子类
 *
 * @author lzlg
 * 2023/3/11 18:22
 */
public class Proxy extends Target {

    private MethodInterceptor methodInterceptor;

    public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
        this.methodInterceptor = methodInterceptor;
    }

    static Method save0;

    static Method save1;

    static Method save2;

    static {
        try {
            save0 = Target.class.getMethod("save");
            save1 = Target.class.getMethod("save", int.class);
            save2 = Target.class.getMethod("save", long.class);
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }

    // MethodProxy是方法代理,生成和代理的方法相同数量的代理方法
    public void saveSuper() {
        super.save();
    }

    public void saveSuper(int i) {
        super.save(i);
    }

    public void saveSuper(long j) {
        super.save(j);
    }

    static MethodProxy save0Proxy;

    static MethodProxy save1Proxy;

    static MethodProxy save2Proxy;

    static {
        // 方法代理创建: 目标类, 代理类, 代理方法标识符, 目标类方法, 代理类方法
        save0Proxy = MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper");
        save1Proxy = MethodProxy.create(Target.class, Proxy.class, "(I)V", "save", "saveSuper");
        save2Proxy = MethodProxy.create(Target.class, Proxy.class, "(J)V", "save", "saveSuper");
    }

    @Override
    public void save() {
        try {
            methodInterceptor.intercept(this, save0, new Object[0], save0Proxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(int i) {
        try {
            methodInterceptor.intercept(this, save1, new Object[]{i}, save1Proxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(long j) {
        try {
            methodInterceptor.intercept(this, save2, new Object[]{j}, save2Proxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
}

/
 * 代理目标对象
 *
 * @author lzlg
 * 2023/3/11 18:22
 */
public class Target {

    public void save() {
        System.out.println("Target save()...");
    }

    public void save(int i) {
        System.out.println("Target save(int i)...");
    }

    public void save(long j) {
       ============ System.out.println("Target save(long j)...");
    }
}

=================================================================
import java.lang.reflect.Method;

/
 * 测试自己实现的代理
 *
 * @author lzlg
 * 2023/3/10 21:14
 */
public class TestMyProxy {
    public static void main(String[] args) {
        Target target = new Target();
        Foo proxy = new $MyProxy0(new MyInvokeHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before...");
                Object result = method.invoke(target, args);
                System.out.println("after...");
                return result;
            }
        });

        proxy.foo();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
        proxy.bar();
    }
}

import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

/
 * 自己实现JDK动态代理
 *
 * @author lzlg
 * 2023/3/10 21:08
 */
public class $MyProxy0 implements Foo {

    private MyInvokeHandler handler;

    public $MyProxy0(MyInvokeHandler handler) {
        this.handler = handler;
    }

    @Override
    public void foo() {
        // 通过一个个调用目标的方法,代码逻辑不一致
//        System.out.println("$Proxy0 before foo()");
//        new Target().foo();
        try {
//            foo.invoke(new Target(), new Object[0]);
            handler.invoke(this, foo, new Object[0]);
            // 运行时的异常进行处理
        } catch (RuntimeException | Error e) {
            throw e;
            // 其他异常,转换为UndeclaredThrowableException抛出
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public int bar() {
        try {
//            foo.invoke(new Target(), new Object[0]);
            return (int) handler.invoke(this, bar, new Object[0]);
            // 运行时的异常进行处理
        } catch (RuntimeException | Error e) {
            throw e;
            // 其他异常,转换为UndeclaredThrowableException抛出
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    // 把方法转换为静态成员遍历,不用每次调用都反射生成
    static Method foo;

    static Method bar;

    static {
        try {
            foo = Foo.class.getMethod("foo");
            bar = Foo.class.getMethod("bar");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }

}

/
 * 接口
 *
 * @author lzlg
 * 2023/3/10 21:07
 */
public interface Foo {

    void foo();

    int bar();
}

import java.lang.reflect.Method;

/
 * 自己实现动态代理,封装方法调用
 *
 * @author lzlg
 * 2023/3/10 21:09
 */
public interface MyInvokeHandler {

    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

/
 * 目标类
 *
 * @author lzlg
 * 2023/3/10 21:07
 */
public class Target implements Foo {
    @Override
    public void foo() {
        System.out.println("Target foo()...");
    }

    @Override
    public int bar() {
        System.out.println("Target bar()... return 233");
        return 233;
    }
}

3)Spring中的AOP实现

import org.springframework.aop.framework.Advised;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.lang.reflect.Method;

/
 * 测试Spring代理增强的特点
 * 1.代理对象和原始对象的数据不共用,需要通过代理对象的方法才能访问到原始对象中的数据
 * 2.原始对象的private(私有), static(静态), final(不能继承)的方法不能被代理增强
 *
 * @author lzlg
 * 2023/4/9 19:46
 */
@SpringBootApplication
public class TestSpringProxyFeature {
    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(TestSpringProxyFeature.class, args);
        // 被增强的Bean,通过getBean方法返回的是代理
        Bean1 proxy = context.getBean(Bean1.class);
        System.out.println(proxy);

        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 可发现代理对象中成员变量bean2为null和initialized为false
        // 原对象中的成员变量bean2不为null且initialized为true
        showProxy(proxy);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 只有普通的成员方法m1被增强了
        proxy.m1();
        proxy.m2();
        proxy.m3();

        Method m4 = Bean1.class.getDeclaredMethod("m4");
        m4.setAccessible(true);
        m4.invoke(proxy);
        context.close();
    }

    private static void showProxy(Bean1 proxy) throws Exception {
        System.out.println("代理中的成员变量: >>>>>>>>>");
        System.out.println("bean2 == " + proxy.bean2);
        System.out.println("initialized == " + proxy.initialized);

        if (proxy instanceof Advised) {
            Advised advised = (Advised) proxy;
            Bean1 target = (Bean1) advised.getTargetSource().getTarget();
            System.out.println("原对象中的成员变量: >>>>>>>>>");
            System.out.println("bean2 == " + target.bean2);
            System.out.println("initialized == " + target.initialized);
        }
    }

}

import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

/
 * 测试Spring中的代理
 *
 * @author lzlg
 * 2023/3/11 19:26
 */
public class TestSpringProxy {
    public static void main(String[] args) {
        // 1.创建切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");

        // 2.创建通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before...");
            Object result = invocation.proceed();
            System.out.println("after...");
            return result;
        };

        // 3.创建advisor
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

        // 4.创建代理
        // 使用JDK代理还是使用CGLIB代理
        // proxyTargetClass是ProxyFactory中的一个属性,从public class ProxyConfig中继承的
        // a.如果proxyTargetClass为true,则使用CGLIB代理
        // b.如果proxyTargetClass为false,且设置了实现的接口信息,用JDK代理
        // c.如果proxyTargetClass为false,没有设置实现的接口信息,用CGLIB代理

//        FirstTarget target = new FirstTarget();
        TwoTarget target = new TwoTarget();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target);
        factory.setInterfaces(target.getClass().getInterfaces());
        factory.addAdvisor(advisor);
//        T proxy = (T) factory.getProxy();
        TwoTarget proxy = (TwoTarget) factory.getProxy();
        System.out.println(proxy.getClass());
        proxy.foo();
        System.out.println("===================");
        proxy.bar();
    }


    interface T {
        void foo();

        void bar();
    }

    static class FirstTarget implements T {

        @Override
        public void foo() {
            System.out.println("FirstTarget foo()...");
        }

        @Override
        public void bar() {
            System.out.println("FirstTarget bar()...");
        }
    }

    static class TwoTarget {
        public void foo() {
            System.out.println("TwoTarget foo()...");
        }

        public void bar() {
            System.out.println("TwoTarget foo()...");
        }
    }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/
 * @author lzlg
 * 2023/4/9 19:50
 */
@Component
public class Bean1 {

    Bean2 bean2;

    boolean initialized;

    /
     * 依赖注入
     */
    @Autowired
    public void setBean2(Bean2 bean2) {
        System.out.println(">>>>> Bean1 @Autowired....");
        this.bean2 = bean2;
    }

    public Bean2 getBean2() {
        return bean2;
    }

    public boolean isInitialized() {
        return initialized;
    }

    /
     * 初始化方法
     */
    @PostConstruct
    public void init() {
        System.out.println(">>>>> Bean1 init()....");
        this.initialized = true;
    }

    public void m1() {
        System.out.println("Bean1 normal m1()...");
    }

    public final void m2() {
        System.out.println("Bean1 final m2()...");
    }

    public static void m3() {
        System.out.println("Bean1 static m3()...");
    }

    private void m4() {
        System.out.println("Bean1 private m4()...");
    }
}

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/
 * @author lzlg
 * 2023/4/9 19:51
 */
@Aspect
@Component
public class Bean1Aspect {

    /
     * 对Bean1的所有方法进行增强
     */
    @Before("execution(* com.lzlg.study.spring.proxy.spring.Bean1.*(..))")
    public void before() {
        System.out.println("Bean1Aspect >>>>> before...");
    }
}

import org.springframework.stereotype.Component;

/
 * @author lzlg
 * 2023/4/9 19:50
 */
@Component
public class Bean2 {
}

4)Spring中的增强Advisor

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.*;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

;

/
 * 测试Spring中切面通知
 *
 * @author lzlg
 * 2023/3/11 20:26
 */
public class TestSpringAdvisor {
    public static void main(String[] args) throws Throwable {
        // 创建Aspect的实例工厂对象
        AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new AspectOne());

        List<Advisor> advisors = new ArrayList<>();
        // 模拟解析Aspect切面转换为Advisor切面
        for (Method method : AspectOne.class.getDeclaredMethods()) {
            // 解析@Before前置通知
            if (method.isAnnotationPresent(Before.class)) {
                Before before = method.getAnnotation(Before.class);
                // 1.切点
                AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
                pointcut.setExpression(before.value());
                // 2.advice通知
                AspectJMethodBeforeAdvice beforeAdvice = new AspectJMethodBeforeAdvice(method, pointcut, factory);
                // 3.advisor
                Advisor advisor = new DefaultPointcutAdvisor(pointcut, beforeAdvice);
                advisors.add(advisor);
                // 解析@After后置通知
            } else if (method.isAnnotationPresent(After.class)) {
                After after = method.getAnnotation(After.class);
                // 1.切点
                AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
                pointcut.setExpression(after.value());
                // 2.advice通知
                AspectJAfterAdvice afterAdvice = new AspectJAfterAdvice(method, pointcut, factory);
                // 3.advisor
                Advisor advisor = new DefaultPointcutAdvisor(pointcut, afterAdvice);
                advisors.add(advisor);
            }
        }
        for (Advisor advisor : advisors) {
            System.out.println(advisor);
        }

        System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");

        FirstTarget target = new FirstTarget();
        // 所有的通知都适配成环绕通知进行调用,环绕通知都实现了MethodInterceptor接口,使用了适配器模式
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        // 通过ExposeInvocationInterceptor这个通知才能暴露MethodInvocation到当前执行线程
        proxyFactory.addAdvice(ExposeInvocationInterceptor.INSTANCE);
        proxyFactory.addAdvisors(advisors);
        // 得到所有的封装完成的通知信息
        List<Object> adviceList = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(
                FirstTarget.class.getMethod("foo"), FirstTarget.class);
        for (Object advice : adviceList) {
            // 可以看到AspectJAfterAdvice转换成了MethodBeforeAdviceInterceptor
            System.out.println(advice);
        }
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 执行调用链
        MethodInvocation invocation = new ReflectiveMethodInvocation(
                null, target, FirstTarget.class.getMethod("foo"), new Object[0], FirstTarget.class, adviceList
        ) {
        };
        invocation.proceed();


    }

    private static void testAspectJPostCreator() {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("aspectOne", AspectOne.class);
        context.registerBean("config", Config.class);
        context.registerBean(ConfigurationClassPostProcessor.class);
        // 处理切面的bean后置处理器,在创建后依赖注入之前执行
        // 在初始化之后执行
        context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
        context.refresh();

//        String[] beanDefinitionNames = context.getBeanDefinitionNames();
//        for (String beanDefinitionName : beanDefinitionNames) {
//            System.out.println(beanDefinitionName);
//        }

//        AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);

        context.close();
    }

    static class FirstTarget {
        public void foo() {
            System.out.println("FirstTarget foo()...");
        }
    }

    static class TwoTarget {
        public void bar() {
            System.out.println("TwoTarget bar()...");
        }
    }

    // 高级切面AspectJ
    @Aspect
    static class AspectOne {

        @Before("execution(* foo())")
        public void before() {
            System.out.println("AspectOne before...");
        }

        @After("execution(* foo())")
        public void after() {
            System.out.println("AspectOne after...");
        }
    }

    @Configuration
    static class Config {
        // 低级切面Advisor
        @Bean
        public Advisor advisor3(MethodInterceptor advice3) {
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* foo())");
            return new DefaultPointcutAdvisor(pointcut, advice3);
        }

        @Bean
        public MethodInterceptor advice3() {
            return invocation -> {
                System.out.println("advice3 before...");
                Object result = invocation.proceed();
                System.out.println("advice3 after...");
                return result;
            };
        }
    }
}

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

import java.lang.reflect.Field;
import java.util.List;

/
 * 测试Spring中的动态通知
 *
 * @author lzlg
 * 2023/3/15 19:45
 */
public class TestSpringDynamicAdvice {

    static class Target {
        public void foo(int x) {
            System.out.println("Target foo(x=" + x + ")...");
        }
    }

    @Aspect
    static class MyAspect {
        // 静态通知,无参数绑定,执行时无须使用切点,性能较高
        @Before("execution(* foo())")
        public void before1() {
            System.out.println("MyAspect static before()...");
        }

        // 动态通知,有参数绑定,执行时需使用切点,性能较差
        @Before("execution(* foo()) && args(x)")
        public void before2(int x) {
            System.out.println("MyAspect dynamic before(x=" + x + ")...");
        }
    }

    @Configuration
    static class MyConfig {
        @Bean
        AnnotationAwareAspectJAutoProxyCreator proxyCreator() {
            return new AnnotationAwareAspectJAutoProxyCreator();
        }

        @Bean
        public MyAspect myAspect() {
            return new MyAspect();
        }
    }

    public static void main(String[] args) throws Throwable {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean(ConfigurationClassPostProcessor.class);
        context.registerBean(MyConfig.class);
        context.refresh();

        AbstractAdvisorAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
        List<Advisor> advisors = (List<Advisor>) AbstractAdvisorAutoProxyCreator.class
                .getMethod("findEligibleAdvisors", Class.class, String.class)
                .invoke(creator, Target.class, "target");

        Target target = new Target();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.getProxy();

        List<Object> adviceLst = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(
                Target.class.getMethod("foo", int.class), Target.class);
        for (Object o : adviceLst) {
            System.out.println(o);
        }

    }

    public static void showDetail(Object o) {
        try {
            Class<?> clazz = Class.forName("org.springframework.aop.framework.InterceptorAndDynamicMethodMatcher");
            if (clazz.isInstance(o)) {
                Field methodMatcher = clazz.getDeclaredField("methodMatcher");
                methodMatcher.setAccessible(true);
                Field methodInterceptor = clazz.getDeclaredField("interceptor");
                methodInterceptor.setAccessible(true);
                System.out.println("环绕通知和切点:" + o);
                System.out.println("\t切点为:" + methodMatcher.get(o));
                System.out.println("\t通知为:" + methodInterceptor.get(o));
            } else {
                System.out.println("普通环绕通知:" + o);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/
 * 测试Spring中通知调用链
 *
 * @author lzlg
 * 2023/3/15 19:18
 */
public class TestSpringInvocation {
    // 目标类
    static class Target {
        public void foo() {
            System.out.println("Target foo()...");
        }
    }

    // 第一个环绕通知
    static class FirstAdvice implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("FirstAdvice before...");
            Object result = invocation.proceed();
            System.out.println("FirstAdvice after...");
            return result;
        }
    }

    // 第二个环绕通知
    static class SecondAdvice implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("SecondAdvice before...");
            Object result = invocation.proceed();
            System.out.println("SecondAdvice after...");
            return result;
        }
    }

    // 自己实现的调用链
    static class MyInvocation implements MethodInvocation {
        // 目标
        private Object target;
        // 代理方法(被环绕的方法)
        private Method method;
        // 代理方法的参数数组
        private Object[] args;
        // 环绕通知列表
        private List<MethodInterceptor> methodInterceptorList;
        // 调用计数器
        private int counter;

        public MyInvocation(Object target, Method method, Object[] args, List<MethodInterceptor> methodInterceptorList) {
            this.target = target;
            this.method = method;
            this.args = args;
            this.methodInterceptorList = methodInterceptorList;
            this.counter = 1;
        }

        @Override
        public Method getMethod() {
            // 获取被代理方法
            return method;
        }


        @Override
        public Object[] getArguments() {
            // 获取方法参数
            return args;
        }

        @Override
        public Object proceed() throws Throwable {
            // 如果调用次数已经超过环绕通知列表的数量,则应调用目标方法了
            if (counter > methodInterceptorList.size()) {
                return method.invoke(target, args);
            }
            // 递归调用环绕通知,计数器+1
            MethodInterceptor interceptor = methodInterceptorList.get(counter++ - 1);
            return interceptor.invoke(this);
        }

        @Override
        public Object getThis() {
            // 目标对象
            return target;
        }

        @Override
        public AccessibleObject getStaticPart() {
            return method;
        }
    }

    public static void main(String[] args) throws Throwable {
        Target target = new Target();
        List<MethodInterceptor> methodInterceptorList = Arrays.asList(
                new FirstAdvice(),
                new SecondAdvice()
        );
        // 这里体现了职责链的设计模式
        MyInvocation invocation = new MyInvocation(target, Target.class.getMethod("foo"),
                new Object[0], methodInterceptorList);
        invocation.proceed();
    }
}

import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;

/
 * 测试Spring中的切点
 *
 * @author lzlg
 * 2023/3/11 19:51
 */
public class TestSpringPointCut {
    public static void main(String[] args) throws Exception {
        // 1.使用AspectJ的表达式的切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");
        System.out.println("T1 match foo()? " + pointcut.matches(T1.class.getMethod("foo"), T1.class));
        System.out.println("T1 match bar()? " + pointcut.matches(T1.class.getMethod("bar"), T1.class));
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>.");
        // 2.使用@annotation指定注解的切点,但只能匹配方法上的@Transactional注解
        AspectJExpressionPointcut annotationPointCut = new AspectJExpressionPointcut();
        annotationPointCut.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
        System.out.println("T1 match foo()? " + annotationPointCut.matches(T1.class.getMethod("foo"), T1.class));
        System.out.println("T1 match bar()? " + annotationPointCut.matches(T1.class.getMethod("bar"), T1.class));
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>.");
        // 3.可匹配类和接口上@Transactional注解的切点
        StaticMethodMatcherPointcut matcherPointcut = new StaticMethodMatcherPointcut() {
            // 自定义切点匹配逻辑
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                // 检查方法上是否有@Transactional注解
                MergedAnnotations annotations = MergedAnnotations.from(method);
                if (annotations.isPresent(Transactional.class)) {
                    return true;
                }
                // 检查类上是否有@Transactional注解
//                annotations = MergedAnnotations.from(targetClass);
//                if (annotations.isPresent(Transactional.class)) {
//                    return true;
//                }
                // 检查类的接口和本类上是否有@Transactional注解
                annotations = MergedAnnotations.from(targetClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
                if (annotations.isPresent(Transactional.class)) {
                    return true;
                }
                return false;
            }
        };
        System.out.println("T1 match foo()? " + matcherPointcut.matches(T1.class.getMethod("foo"), T1.class));
        System.out.println("T1 match bar()? " + matcherPointcut.matches(T1.class.getMethod("bar"), T1.class));
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>.");
        System.out.println("T2 match foo()? " + matcherPointcut.matches(T2.class.getMethod("foo"), T2.class));
        System.out.println("T2 match bar()? " + matcherPointcut.matches(T2.class.getMethod("bar"), T2.class));
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>.");
        System.out.println("T3 match foo()? " + matcherPointcut.matches(T3.class.getMethod("foo"), T3.class));
        System.out.println("T3 match bar()? " + matcherPointcut.matches(T3.class.getMethod("bar"), T3.class));
    }

    static class T1 {
        @Transactional
        public void foo() {
        }

        public void bar() {
        }
    }

    @Transactional
    static class T2 {
        public void foo() {
        }

        public void bar() {
        }
    }

    @Transactional
    interface I {
        void foo();

        void bar();
    }

    static class T3 implements I {
        @Override
        public void foo() {

        }

        @Override
        public void bar() {

        }
    }
}
Spring Boot
程序员内功
  • 作者:lzlg520
  • 发表时间:2023-06-14 15:01
  • 版权声明:自由转载-非商用-非衍生-保持署名
  • 公众号转载:请在文末添加作者公众号二维码