前言
金九银十之际,又到了面试的黄金时段,相信每位猿友或多或少再被影响着…
翻出许久的面试总结册,陷入沉思中…(这玩意多多少少就是有些废头发)…
圆规正转,今日份总结 spring5中常用注解的使用方法及一些心得。
在此,记录一下,分享给大家。
注解介绍
spring5中常用注解,大致可以归为四类组件:
配置类组件、赋值(自动装配)组件、织入组件、切面组件。
配置组件(Configure Components)
-
@Configuration: 用于定义配置类,可替换XML配置文件,被注解的类内部包含一个或多个@Bean注解方法。可以被AnnotationConfigApplicationContext或者AnnotationConfigWebApplicationContext 进行扫描。用于构建bean定义以及初始化Spring容器。
/** * 配置类 */ @Configuration public class YysConfig { @Bean public Apple apple() { return new Apple(); } @Bean("banana_bean") public Banana banana() { return new Banana(); } @Bean public Pear pear() { return new Pear(); } }
/** * 测试类 */ public class YysTest { @Test public void test() { ApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class); System.out.println("\n----------输出结果----------\n"); System.out.println(app.getBean("apple")); // 默认使用方法名 System.out.println(app.getBean("banana_bean")); // 配置别名优先使用别名,用发方法名报错 System.out.println(app.getBean("pear")); } }
-
@ComponentScan: 扫包,相当于xml配置文件中的context:component-scan,默认会扫描该类所在包下所有的配置类。
支持自定义规则:
/** * 配置类 */ @Configuration @ComponentScan( value = "com.yys.study.spring.annotation.config", // includeFilters = {@Filter(type = FilterType.ANNOTATION, value = {Component.class} )}, // 使用某个注解 // includeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, value = {Pitaya.class} )}, // 使用具体某个类 includeFilters = { @Filter(type = FilterType.CUSTOM, value = { YysTypeFilter.class} )}, // 自定义规则类 useDefaultFilters = false ) public class YysConfig { }
/** * 自定义规则类 */ public class YysTypeFilter implements TypeFilter { /** * @param metadataReader 获取当前正在操作类的信息 * @param metadataReaderFactory 获取上下文中所有的信息 */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // 获得当前类的所有注解的信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); // 获得当前扫描到的类的信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); // 获取当前类的所有资源信息 Resource resource = metadataReader.getResource(); /** * 自定义规则 */ String className = classMetadata.getClassName(); System.out.println("----------" + className + "------------"); // 筛选出包含"Test"的类 if (className.contains("Test")) return true; return false; } }
/** * 测试类 */ public class YysTest { @Test public void test() { ApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class); String[] beanDefinitionNames = app.getBeanDefinitionNames(); System.out.println(Arrays.toString(beanDefinitionNames) .replaceAll("\\[|\\]", "") .replaceAll(", ", "\n")); } }
-
不加自定义规则:
-
加自定义规则:
-
@Scope: 用于指定scope作用域的(用在类上),默认单例
/** * 配置类 */ @Configuration public class YysConfig { /** * 0. 默認是單例 * 1. prototype - 原型,多例 * 2. singleton - 单例 * 3. request - 主要应用于web模块,同一次请求只创建一个实例 * 4. session - 主要应用于web模块,同一个session只创建一个对象 */ @Scope("prototype") @Bean public Apple apple() { return new Apple(); } }
-
@Lazy: 延迟加载初始化
/** * 配置类 */ @Configuration public class YysConfig { /** * 默认是非延时加载 * 延时加载/懒加载只针对单例Bean起作用 * * 作用:容器启动时不创建对象,调用对象时才创建 */ @Lazy @Bean public Apple apple() { return new Apple(); } }
-
@Conditional: spring4开始提供,作用是按照一定的条件进行判断,满足条件给容器注册Bean
/** * 配置类 */ @Configuration public class YysConfig { @Conditional(WindowsCondition.class) @Bean public Apple apple() { System.out.println("apple对象已添加至IOC容器"); return new Apple(); } @Conditional(LinuxCondition.class) @Bean public Banana banana() { System.out.println("banana对象已添加至IOC容器"); return new Banana(); } }
/** * 自定义规则类 - Windows */ public class WindowsCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory(); Environment environment = conditionContext.getEnvironment(); String osName = environment.getProperty("os.name"); System.out.println("当前操作系统环境为:" + osName); if(osName.contains("Windows")) return true; return false; } }
/** * 自定义规则类 - Linux */ public class LinuxCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory(); Environment environment = conditionContext.getEnvironment(); String osName = environment.getProperty("os.name"); System.out.println("当前操作系统环境为:" + osName); if(osName.contains("Linux")) return true; return false; } }
/** * 测试类 */ public class YysTest { @Test public void test() { ApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class); // 如当前操作系统环境为Windows -》 apple对象添加至IOC容器 // 如当前操作系统环境为Linux -》 banana对象添加至IOC容器 } }
知识点:IDEA更换操作系统环境的配置
1. Run -> Edit Configurations
2. VM options +参数配置:-ea -Dos.name=Linux
-
@Import: 导入外部资源,直接加载至ioc容器(导入的是全类名)
/** * 配置类 */ @Configuration @Import(Apple.class) // @Import(value = {Apple.class, Banana.class}) public class YysConfig { }
/** * 测试类 */ public class YysTest { @Test public void test() { ApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class); String[] beanDefinitionNames = app.getBeanDefinitionNames(); System.out.println(Arrays.toString(beanDefinitionNames) .replaceAll("\\[|\\]", "") .replaceAll(", ", "\n")); } }
【知识点】给IOC容器注册bean的方式:
- @Bean 直接加载单个类
- @ComponentScan 默认扫描(@Controller、@Service、@Repostory、@Component)
- @Import 快速给容器导入Bean的方式
a.@Import 直接参数导入
b.自定义规则类,需实现ImportSelector接口
c.实现ImportBeanDefinitionRegistrar接口,获得BeanDefinitionRegistry可以手动往IOC容器塞 - FactoryBean 把需要注册的对象封装为FactoryBean
a.FactoryBean:负责将Bean注册到IOC的Bean
b.BeanFactory:从IOC容器中获得Bean对象
-
对Bean生命周期的监控:
-
配置@Bean的参数
/** * 火龙果 */ public class Pitaya { public Pitaya() { System.out.println("Pitaya初始化完成..."); } public void before() { System.out.println("----- before -----"); } public void service() { System.out.println("----- service -----"); } public void after() { System.out.println("----- after -----"); } }
/** * 配置类 */ @Configuration public class YysConfig { @Bean(initMethod = "before", destroyMethod = "after") public Pitaya pitaya() { return new Pitaya(); } }
/** * 测试类 */ public class YysTest { @Test public void test() { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class); Pitaya pitaya = (Pitaya) app.getBean("pitaya"); pitaya.service(); app.close(); // 关闭容器 } }
-
分别实现InitializingBean、DisposableBean接口
/** * 橘子 */ @Component public class Orange implements InitializingBean, DisposableBean { public Orange() { System.out.println("Orange初始化完成..."); } public void service() { System.out.println("----- 业务 -----"); } @Override public void destroy() throws Exception { System.out.println("----- 销毁 -----"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("----- 初始化 -----"); } }
/** * 配置类 */ @Configuration @ComponentScan("com.yys.study.spring.entity") public class YysConfig { }
/** * 测试类 */ public class YysTest { @Test public void test() { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class); Orange orange = (Orange) app.getBean("orange"); orange.service(); app.close(); // 关闭容器 } }
-
使用@PostConstruct和@PreDestory注解
/** * 西瓜 */ @Component public class Watermelon { public Watermelon() { System.out.println("Watermelon初始化完成..."); } @PostConstruct // 初始化之后调用 public void before() { System.out.println("----- before -----"); } public void service() { System.out.println("----- 业务 -----"); } @PreDestroy // 对象销毁前调用 public void after() { System.out.println("----- after -----"); } }
/** * 配置类 */ @Configuration @ComponentScan("com.yys.study.spring.entity") public class YysConfig { }
/** * 测试类 */ public class YysTest { @Test public void test() { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class); Watermelon watermelon = (Watermelon) app.getBean("watermelon"); watermelon.service(); app.close(); // 关闭容器 } }
-
自定义类实现 BeanPostProcessor接口 - 推荐,自己定义规则
/** * 自定义控制类 */ @Component public class YysBeanPostProcessor implements BeanPostProcessor { @Nullable public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("=== postProcessBeforeInitialization, " + beanName + ", " + bean); return bean; } @Nullable public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("=== postProcessAfterInitialization, " + beanName + ", " + bean); return bean; } }
/** * 葡萄 */ @Component public class Grapes { public Grapes() { System.out.println("Grapes初始化完成..."); } public void service() { System.out.println("----- 业务 -----"); } }
/** * 配置类 */ @Configuration @ComponentScan({ "com.yys.study.spring.annotation.lifecycle.beanpostprocessor", "com.yys.study.spring.entity"}) //@ComponentScans( // @ComponentScan("com.yys.study.spring.entity"), // @ComponentScan("com.yys.study.spring.xxx") //) public class YysConfig { }
/** * 测试类 */ public class YysTest { @Test public void test() { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class); Grapes grapes = (Grapes) app.getBean("grapes"); grapes.service(); app.close(); // 关闭容器 } }
赋值(自动装配)组件(Injection Components)
-
@Component: 泛指组件,当组件不好归类的时候,可以使用此注解进行标注
-
@Controller: 用于标注控制层组件
-
@Service: 用于标注业务层组件
-
@Repository: 用于标注数据访问层组件,即DAO组件
-
@Value: 普通数据类型赋值
- 基本数据类型 @Value(“xxx”)
- 支持Spring EL表达式 @Value(#{8-5})
- 配合@PropertySource注解,通过配置文件赋值 @Value(“bird.color”)
知识点:通过环境变量拿配置
ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
Environment environment = app.getEnvironment();
environment.getProperty(“bird.color”);
-
@Autowired: 默认按类型装配,如想按名称装配,可以结合@Qualifier注解一起使用
-
@PropertySource: 读取配置文件赋值
-
@Qualifier: 如存在多个实例配合使用,优先级高于@Autowired,但要和@Autowired配合使用
-
@Primary: 自动装配出现多个Bean候选者,被注解为@Primary的Bean作为首选者,否则将抛出异常
-
@Resource: 默认按名称装配,当找不到名称匹配的bean才会按类型装配,可以单独使用,优先级高于@Qualifier/@Autowired
简单理解:
@Autowired:根据类型注入
@Resource:默认根据名字注入,找不到按照类型搜索
@Autowired @Qualifier(“beanName”) :两个结合起来可以根据名字和类型注入
织入组件(Weave Components)
-
@ApplicationContextAware: 可以通过这个上下文对象得到Spring容器中的Bean
/** * 当一个类实现 ApplicationContextAware接口之后,这个类就可以方便获得ApplicationContext中的所有bean。 * 换句话说,就是这个类可以直接获取spring配置文件中,所有有引用到的bean对象 */ @Component public class AppUtils implements ApplicationContextAware { public static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * 获取applicationContext实例 */ public static ApplicationContext getApplicationContext() { return AppUtils.applicationContext; } /** * 通过名称获取Bean */ public static <T> T getBean(String beanName) throws Exception { checkNull(); return (T) applicationContext.getBean(beanName); } /** * 通过类型获取Bean */ public static <T> T getBean(Class<T> clazz) throws Exception { checkNull(); return (T) applicationContext.getBean(clazz); } /** * 校验 applicationContext是否为空 * * @throws Exception */ public static void checkNull() throws Exception { if (applicationContext == null) throw new Exception("applicationContext为空"); } }
-
@BeanDefinitionRegistryPostProcessor: BeanDefinitionRegistryPostProcessor实现了BeanFactoryPostProcessor接口,是spring框架BeanDefinitionRegistry的后处理器,用来注册额外的BeanDefinition
@Component @Slf4j public class PersonBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { // 注册Bean定义,容器根据定义返回bean log.info("register fruitsBean - 1"); //构造bean定义 BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder .genericBeanDefinition(Fruits.class); //设置依赖 beanDefinitionBuilder.addPropertyReference("apple", "apple"); BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder .getRawBeanDefinition(); //注册bean定义 registry.registerBeanDefinition("fruitsBean1", personManagerBeanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 注册Bean实例,使用supply接口 log.info("register fruitsBean - 2"); BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder .genericBeanDefinition(Fruits.class, () -> { Apple apple = beanFactory.getBean(Apple.class); Fruits fruits = new Fruits(); fruits.setApple(apple); return fruits; }); BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder .getRawBeanDefinition(); ((DefaultListableBeanFactory) beanFactory) .registerBeanDefinition("fruitsBean2", personManagerBeanDefinition); } }
切面组件(Aspect Components)
- @EnableTransactionManagement: 添加对事务管理的支持,等同于xml配置方式的 <tx:annotation-driven />
- @Transactionl: 配置声明式事务信息
大家好,我是猿医生 ~
在码农的大道上,唯有自己强才是真正的强者,求人不如求己,静下心来,开始行动吧…