springboot 自动装配

创建一个简单的项目:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.1.12.RELEASE</version>
    </parent>

    <groupId>com.xiazhi</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <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>
        </dependency>
    </dependencies>


</project>
pom

首先创建自定义注解:

package com.xiazhi.demo.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * MyComponent 作用于类上,表示这是一个组件,于component,service注解作用相同
 * @author zhaoshuai
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {

}
package com.xiazhi.demo.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 作用于字段上,自动装配的注解,与autowired注解作用相同
 * @author zhaoshuai
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Reference {
}

然后写配置类:

package com.xiazhi.demo.config;

import com.xiazhi.demo.annotation.MyComponent;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;


/**
 * @author ZhaoShuai
 * @company lihfinance.com
 * @date Create in 2020/3/21
 **/
public class ComponentAutoConfiguration implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {

    private ResourceLoader resourceLoader;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        String className = annotationMetadata.getClassName();
        String basePackages = className.substring(0, className.lastIndexOf("."));

        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanDefinitionRegistry, false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(MyComponent.class));
        scanner.scan(basePackages);
        scanner.setResourceLoader(resourceLoader);
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

}

上面是配置扫描指定包下被MyComponent注解标注的类并注册为spring的bean,bean注册成功后,下面就是属性的注入了

package com.xiazhi.demo.config;

import com.xiazhi.demo.annotation.MyComponent;
import com.xiazhi.demo.annotation.Reference;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;

/**
 * @author ZhaoShuai
 * @company lihfinance.com
 * @date Create in 2020/3/21
 **/
@SpringBootConfiguration
public class Configuration implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Bean
    public BeanPostProcessor beanPostProcessor() {
        return new BeanPostProcessor() {

            /**
             * @company lihfinance.com
             * @author create by ZhaoShuai in 2020/3/21
             * 在bean注册前会被调用
             * @param [bean, beanName]
             * @return java.lang.Object
             **/
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                return bean;
            }

            /**
             * @company lihfinance.com
             * @author create by ZhaoShuai in 2020/3/21
             * 在bean注册后会被加载,本次在bean注册成功后注入属性值
             * @param [bean, beanName]
             * @return java.lang.Object
             **/
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                Class<?> clazz = bean.getClass();
                if (!clazz.isAnnotationPresent(MyComponent.class)) {
                    return bean;
                }

                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (!field.isAnnotationPresent(Reference.class)) {
                        continue;
                    }
                    Class<?> type = field.getType();
                    Object obj = applicationContext.getBean(type);
                    ReflectionUtils.makeAccessible(field);
                    ReflectionUtils.setField(field, bean, obj);
                }
                return bean;
            }
        };
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

下面开始使用注解来看看效果:

package com.xiazhi.demo.service;

import com.xiazhi.demo.annotation.MyComponent;

import javax.annotation.PostConstruct;

/**
 * @author ZhaoShuai
 * @company lihfinance.com
 * @date Create in 2020/3/21
 **/
@MyComponent
public class MyService {

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

    public void test() {
        System.out.println("测试案例");
    }
}
View Code
package com.xiazhi.demo.service;

import com.xiazhi.demo.annotation.MyComponent;
import com.xiazhi.demo.annotation.Reference;

/**
 * @author ZhaoShuai
 * @company lihfinance.com
 * @date Create in 2020/3/21
 **/
@MyComponent
public class MyConsumer {

    @Reference
    private MyService myService;

    public void aaa() {
        myService.test();
    }
}
View Code

启动类要引入配置文件:

 import注解引入配置文件。

编写测试类测试:

@SpringBootTest(classes = ApplicationRun.class)
@RunWith(SpringRunner.class)
public class TestDemo {

    @Autowired
    public MyConsumer myConsumer;

    @Test
    public void fun1() {
        myConsumer.aaa();
    }
}
原文地址:https://www.cnblogs.com/Zs-book1/p/12540571.html