Spring中的注解
Spring Framework 注解 | 场景说明 | 起始版本 |
---|---|---|
@Repository | 数据仓储模式注解 | 2.0 |
@Component | 通用组件模式注解 | 2.5 |
@Service | 服务模式注解 | 2.5 |
@Controller | Web 控制器模式注解 | 2.5 |
@Configuration | 配置类模式注解 | 3.0 |
@Component
作为一种由 Spring 容器托管的通用模式组件,任何被 @Component 标准的组件均为组件扫描的候选对象。类
似地,凡是被 @Component 元标注(meta-annotated)的注解,如 @Service ,当任何组件标注它时,也被视作组件扫描的候选对象
装配方式
-
xml
context:component-scan 方式
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"@ComponentScan 方式 自定义模式注解 @Component “派生性” @Component @Repository FirstLevelRepository xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/springcontext.xsd"> <!-- 激活注解驱动特性 --> <context:annotation-config /> <!-- 找寻被 @Component 或者其派生 Annotation 标记的类(Class),将它们注册为 Spring Bean --> <context:component-scan base-package="com.imooc.dive.in.spring.boot" /> </beans>
-
注解
@ComponentScan 方式
@ComponentScan(basePackages = "com.*.*spring.boot")
public class SpringConfiguration {
...
}
Spring @Enable 模块装配
Spring Framework 3.1 开始支持”@Enable 模块驱动“。所谓“模块”是指具备相同领域的功能组件集合, 组合所形成一个独立的单元。比如 Web MVC 模块、AspectJ代理模块、Caching(缓存)模块、JMX(Java 管 理扩展)模块、Async(异步处理)模块等
框架实现 | @Enable 注解模块 | 激活模块 |
---|---|---|
Spring Framework | @EnableWebMvc | Web MVC 模块 |
@EnableTransactionManagement | 事务管理模块 | |
@EnableCaching | Caching 模块 | |
@EnableMBeanExport | JMX 模块 | |
@EnableAsync | 异步处理模块 | |
EnableWebFlux | Web Flux 模块 | |
@EnableAspectJAutoProxy | AspectJ 代理模块 | |
Spring Boot | @EnableAutoConfiguration | 自动装配模块 |
@EnableManagementContext | Actuator 管理模块 | |
@EnableConfigurationProperties | 配置属性绑定模块 | |
@EnableOAuth2Sso | OAuth2 单点登录模块 |
实现方式
-
注解驱动方式
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc { } @Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { ... }
-
接口编程方式
@ Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(CachingConfigurationSelector.class) public @interface EnableCaching { ... } p ublic class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> { /** * {@inheritDoc} * @return {@link ProxyCachingConfiguration} or {@code AspectJCacheConfiguration} for * {@code PROXY} and {@code ASPECTJ} values of {@link EnableCaching#mode()}, respectively */ public String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] { AutoProxyRegistrar.class.getName(),ProxyCachingConfiguration.class.getName() }; case ASPECTJ: return new String[] { AnnotationConfigUtils.CACHE_ASPECT_CONFIGURATION_CLASS_NAME }; default: return null; } }
AdviceModeImportSelector扩展ImportSelecto接口,如果自定义实现只需要实现ImportSelecto接口
public interface ImportSelector { /** * Select and return the names of which class(es) should be imported based on * the {@link AnnotationMetadata} of the importing @{@link Configuration} class. */ String[] selectImports(AnnotationMetadata importingClassMetadata); }
-
-
自定义 @Enable 模块
基于注解驱动实现 - @EnableHelloWorld
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented //@Import(HelloWorldConguration.class) @Import(HelloWorldImportSelector.class) public @interface EnableHelloWorld { }
@Configuration
public class HelloWorldConguration {
/**
* 返回值可以是任意类型的
* @return
*/
@Bean
public HelloWorld helloworld(){
HelloWorld helloWorld = new HelloWorld();
helloWorld.setAge(18);
helloWorld.setBirthday(new Date());
helloWorld.setName("张三");
return helloWorld;
}
}
- Selector实现
/**
* ImportSelector 实现
*/
public class HelloWorldImportSelector implements ImportSelector{
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.err.println(importingClassMetadata.getAnnotationTypes());
System.err.println(importingClassMetadata.getClassName());
return new String[]{HelloWorldConguration.class.getName()};
}
}
Spring 条件装配
从 Spring Framework 3.1 开始,允许在 Bean 装配时增加前置条件判断
Spring 注解 | 场景说明 | 起始版本 |
---|---|---|
@Profile | 配置化条件装配 | 3.1 |
@Conditional | 编程条件装配 | 4.0 |
这里只说Conditional
- 注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Conditional(OnMyUserConditional.class)
public @interface ConditionMyUser {
String name();
String value();
}
-
Condition实现
public class OnMyUserConditional implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionMyUser.class.getName()); if(!attributes.isEmpty()){ String name = String.valueOf(attributes.get("name")); String value = String.valueOf(attributes.get("value")); return true; } return false; } }
-
Condition接口
@FunctionalInterface public interface Condition { boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }
测试
public class MyUserBootstarp2 {
@Bean
@ConditionMyUser(name = "user.name",value = "就是不知道")
public String helloUser(){
return "helloUser "+ LocalDateTime.now();
}
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(MyUserBootstarp2.class)
.web(WebApplicationType.NONE)
.run(args);
String helloUser = context.getBean("helloUser",String.class);
System.err.println(helloUser);
//关闭上下文
context.close();
}
}
Spring Boot 自动装配
在 Spring Boot 场景下,基于约定大于配置的原则,实现 Spring 组件自动装配的目的。其中使用了
-
Spring 模式注解装配
-
Spring @Enable 模块装配
-
Spring 条件装配装配
-
Spring 工厂加载机制
-
实现类: SpringFactoriesLoader
-
配置资源: META-INF/spring.factories
自动装配举例
参考 META-INF/spring.factories
实现方法
- 激活自动装配 - @EnableAutoConfiguration
- 实现自动装配 - XXXAutoConfiguration
- 配置自动装配实现 - META-INF/spring.factories
自定义自动装配
在启动类上使用@EnableAutoConfiguration
新建MyUserAutoConfiguration
配置自动装配实现 - META-INF/spring.factories
- 条件判断
- @Configuration注解
- @Enable模块
@Configuration
@EnableMyUser
@ConditionMyUser(name = "user.name",value = "自动装配")
public class MyUserAutoConfiguration {
}
@EnableAutoConfiguration
public class MyUserAutoConfigurationBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(MyUserAutoConfigurationBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
MyUser myUser = context.getBean("myUser", MyUser.class);
System.err.println(myUser.toString());
context.close();
}
}
github: https://github.com/ln0491/SpringBootLearning/tree/master/bootlearning