Spring核心注解使用

简介: Spring核心注解使用

xml方式

  • beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
      <bean id="car" class="com.my.source.spring.start.xmlconfig.Car">
            <constructor-arg name="brand" value="my"/>
            <constructor-arg name="wheel" ref="wheel"/>
            <property name="name" value="my-car"/>
      </bean>
      <bean id="wheel" class="com.my.source.spring.start.xmlconfig.Wheel">
            <property name="name" value="my-wheel"/>
      </bean>
</beans>
  • bean
public class Wheel {
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Wheel{" +
                "name='" + name + '\'' +
                '}';
    }
}

public class Car {
    private String name;
    private String brand;
    private Wheel wheel;
    public Car(String brand, Wheel wheel){
        this.brand = brand;
        this.wheel = wheel;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", brand='" + brand + '\'' +
                ", wheel=" + wheel +
                '}';
    }
}
  • Main
public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        System.out.println(context.getBean("car"));
    }
}

Java注解方式

@Bean

public class Person {}


public class Boy {
    public Boy(){
        System.out.println("Boy was init!");
    }
}


public class BoyFactoryBean implements FactoryBean<Boy> {
    public BoyFactoryBean(){
        System.out.println("BoyFactoryBean was init!");
    }
    //返回Bean的对象
    @Override
    public Boy getObject() throws Exception {
        return new Boy();
    }
    //返回Bean的类型
    @Override
    public Class<?> getObjectType() {
        return Boy.class;
    }
    //是否单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}


@Configuration
public class MainConfig {
    @Bean(value = "person")
    //@Scope(value = "prototype")
    //@Lazy
    public Person person1(){
        return new Person();
    }
    @Bean
    public BoyFactoryBean boyFactoryBean(){
        return new BoyFactoryBean();
    }
}
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println(context.getBean("person"));
        System.out.println(context.getBean("boyFactoryBean"));
    }
}

@ComponentScan

@Repository
public class MyDao {}
@Service
public class MyService {}
@Controller
public class MyController {}
  • 一般使用
@ComponentScan(basePackages = {"com.my.source.spring.start.scan"})
@Configuration
public class MainConfig {
}
  • 使用排除过滤器
@ComponentScan(basePackages = {"com.my.source.spring.start.scan"},
        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class}),
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {MyService.class})})
@Configuration
public class MainConfig {
    //此配置将排除使用Controller注解扫描的类和MyService类
}
  • FilterType详细说明
public enum FilterType {
  //指定注解形式
  ANNOTATION,
  //指定的类型
  ASSIGNABLE_TYPE,
  //ASPECTJ形式的
  ASPECTJ,
    //正则
  REGEX,
  //自定义
  CUSTOM
}
  • 使用自定义的过滤器
@Component
public class User {}
public class MyTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类的资源信息
        Resource resource = metadataReader.getResource();
        if ("com.my.source.spring.start.scan.User".equals(annotationMetadata.getClassName())) {
            return true;
        }
        return false;
    }
}

@ComponentScan(basePackages = {"com.my.source.spring.start.scan"},
  includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, value = {MyTypeFilter.class})},
        useDefaultFilters = false)//为false表示只使用上面声明了的filter,不使用Spring自带的过滤器
@Configuration
public class MainConfig {
}

@Import

@Import注解支持三种导入方式

  • 普通的组件
public class Man {
    public Man(){
        System.out.println("Man was init!");
    }
}

@Import({Man.class})
@Configuration
public class MainConfig {
}
  • 实现ImportSelector接口
public class Child {
    public Child(){
        System.out.println("Child was init!");
    }
}

public class MyImport implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.my.source.spring.start.forimport.Child"};
    }
}

@Import({MyImport.class})
@Configuration
public class MainConfig {
}
  • 实现ImportBeanDefinitionRegistrar接口
public class Baby {
    public Baby(){
        System.out.println("Baby was init!");
    }
}

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinition beanDefinition = new RootBeanDefinition(Baby.class);
        registry.registerBeanDefinition("my-baby",beanDefinition);
    }
}

@Import({MyImportBeanDefinitionRegistrar.class})
@Configuration
public class MainConfig {
}

@Conditional


public class Father {
    public Father(){
        System.out.println("Father was init!");
    }
}


public class Son {
    public Son(Father father){
        System.out.println("has father! " + father);
        System.out.println("Son was init!");
    }
}


public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return context.getBeanFactory().containsBean("father");
    }
}


@Configuration
public class MainConfig {
//    @Bean
    public Father father(){
        return new Father();
    }
    @Bean
    @Conditional(MyCondition.class)
    public Son son(Father father){
        return new Son(father);
    }
}

当Father注入到容器中时,Son才会注入

@Autowired

@Repository
public class UserDao {
}


@Service
public class UserService {
  //自动注入
    @Autowired
    private UserDao userDao;
    @Override
    public String toString() {
        return "UserService{" +
                "userDao=" + userDao +
                '}';
    }
}


@Controller
public class UserController {
    private UserService userService;
    //set方式注入
    @Autowired
    public void setUserService(UserService userService){
        this.userService = userService;
    }
    //构造器注入
    @Autowired
    public UserController(UserService userService){
        this.userService = userService;
    }
    @Override
    public String toString() {
        return "UserController{" +
                "userService=" + userService +
                '}';
    }
}

@PropertySource

  • student.properties
name=张三
age=18
score=91.5


public class Student {
    @Value("${name}")
    private String name;
    @Value("${age}")
    private int age;
    @Value("${score}")
    private BigDecimal score;
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}


@Configuration
@PropertySource(value = {"classpath:student.properties"} , encoding = "UTF-8")
public class MainConfig {
    @Bean
    public Student student(){
        return new Student();
    }
}

实现xxxAware接口获取Spring 底层组件

@Component
public class SpringContextUtil implements ApplicationContextAware, BeanNameAware {
    public ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    @Override
    public void setBeanName(String name) {
        System.out.println("current bean name is :【"+name+"】");
    }
}

Bean的初始化和销毁方法

  • 使用@Bean注解指定init和destroy方法
public class People {
    public void init(){
        System.out.println("people be born !");
    }
    public People(){
        System.out.println("People.People");
    }
    public void destroy(){
        System.out.println("people die !");
    }
}


@Configuration
public class MainConfig {
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public People people() {
        return new People();
    }
}
  • 实现InitializingBean, DisposableBean接口
public class Person implements InitializingBean, DisposableBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Person be born !");
    }
    public Person(){
        System.out.println("Person.Person");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("Person die !");
    }
}
  • 使用@PostConstruct和@PreDestroy注解
public class Banana {
    @PostConstruct
    public void init(){
        System.out.println("Banana.init");
    }
    public Banana(){
        System.out.println("Banana.Banana");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("Banana.destroy");
    }
}
  • 实现BeanPostProcessor接口在bean初始化前后实现自定义逻辑
public class MyBeanPostProcessor implements BeanPostProcessor {
    /**
     * 在init方法前调用
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization ===== "+ beanName);
        return bean;
    }
    /**
     * 在init方法后调用
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessAfterInitialization ===== " + beanName);
        return bean;
    }
}
  • Spring bean初始化时的部分源码
    if (mbd == null || !mbd.isSynthetic()) {
            //调用postProcessBeforeInitialization方法
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
            //执行初始化方法
      invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          (mbd != null ? mbd.getResourceDescription() : null),
          beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
            //调用postProcessAfterInitialization方法
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

通过依赖查找的方式一次性注入多个组件

public interface MyService {
    void doService();
}
@Service
public class OneMyServiceImpl implements MyService {
    @Override
    public void doService() {
        System.out.println("OneServiceImpl.doService");
    }
}
@Service
public class TwoMyServiceImpl implements MyService {
    @Override
    public void doService() {
        System.out.println("TwoServiceImpl.doService");
    }
}
@Service
public class ThreeMyServiceImpl implements MyService {
    @Override
    public void doService() {
        System.out.println("ThreeServiceImpl.doService");
    }
}
@Component
public class Business {
    private final Map<String, MyService> serviceMap;
    public Business(Map<String, MyService> serviceMap) {
        this.serviceMap = serviceMap;
    }
    public void doBusiness(){
        serviceMap.forEach((key,service)->{
            service.doService();
        });
    }
}


目录
相关文章
|
1月前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
52 0
|
1天前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
107 73
|
2月前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
149 3
|
1天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
1天前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
28天前
|
前端开发 Java Spring
Spring MVC核心:深入理解@RequestMapping注解
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的核心,它将HTTP请求映射到控制器的处理方法上。本文将深入探讨`@RequestMapping`注解的各个方面,包括其注解的使用方法、如何与Spring MVC的其他组件协同工作,以及在实际开发中的应用案例。
42 4
|
1月前
|
XML JSON Java
SpringBoot必须掌握的常用注解!
SpringBoot必须掌握的常用注解!
68 4
SpringBoot必须掌握的常用注解!
|
28天前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
108 2
|
28天前
|
前端开发 Java Spring
探索Spring MVC:@Controller注解的全面解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序的基石之一。它不仅简化了控制器的定义,还提供了一种优雅的方式来处理HTTP请求。本文将全面解析`@Controller`注解,包括其定义、用法、以及在Spring MVC中的作用。
47 2
|
1月前
|
消息中间件 Java 数据库
解密Spring Boot:深入理解条件装配与条件注解
Spring Boot中的条件装配与条件注解提供了强大的工具,使得应用程序可以根据不同的条件动态装配Bean,从而实现灵活的配置和管理。通过合理使用这些条件注解,开发者可以根据实际需求动态调整应用的行为,提升代码的可维护性和可扩展性。希望本文能够帮助你深入理解Spring Boot中的条件装配与条件注解,在实际开发中更好地应用这些功能。
37 2