一、简介
从spring 3.x开始,spring支持java配置,提供了功能越来越强大的注解配置。下面将对一些实用注解进行介绍。
二、基本配置相关的注解
1、@Configuration
通常注解在类上,表示该类是一个配置类
2、@EnableAspectJAutoProxy
注解在类上,开启spring对AspectJ代理的支持。(备注:切点通用注解在方法上的@Before、@around、@After上,
如@Before("@annotation(hello)"),详情请查看本博客的spring中基于注解的aop);
3、@PropertySource
声明配置文件位置,如@PropertySource("classpath:properties/base.properties"),
同时要声明org.springframework.context.support.PropertySourcesPlaceholderConfigurer,即
@Bean public static PropertySourcesPlaceholderConfigurer propertyConfig(){ return new PropertySourcesPlaceholderConfigurer(); }
三、关于bean的注解
1、声明bean的注解
a) @Component
普通bean的声明
b) @Service
通常是业务逻辑层bean的声明
c) @Repository
通常是数据访问层bean的声明
d) @Controller
通常是展示层bean的声明
e) @Bean
注解在方法上,表示当前方法的返回值是一个bean,bean的名称就是方法名,如
@Bean public Student student(){ Student stu = new Student(); stu.setName("panda"); return stu; }
当然也可以在注解内自定义bean的名称,格式为@Bean(name="beanName"),如
@Bean(name="stu") public Student student(){ Student stu = new Student(); stu.setName("panda"); return stu; }
2、定义bean类型的注解
1、@Scope(类型)
指定bean的创建类型,通常值有singleton(这也是默认类型),即是创建单例,也就是spring容器中只有一个实例;
值也可以是prototype,即是每次调用都会新创建一个bean
3、bean中属性注入的注解(通常)
a) @Autowired
基于类型在属性或set方法上进行bean的注入
b) @Resource
先基于名称,若找不到,再基于类型,在属性或set方法上进行bean的注入
4、bean中属性值注入的注解(@Value)
@Value注解是sping EL表达式语言的注解形式,可以对bean中各属性进行值注入,通常有以下几种:
a) 注入普通字符
@Value("yes") private String flag;
b) 注入操作系统属性
@Value("#{systemProperties['os.name']}") private String osName;
c) 注入表达式运算结果
@Value("#{T(java.lang.Math).random()}") private double rand;
d) 注入文件内容
@Value("classpath:properties/base.properties") private Resource basePro;
e) 注入网址内容
@Value("http://www.baidu.com") private Resource urlTxt;
f) 注入属性文件中的属性()
@Value("${myname}") private String myname;
特别注意的是:进行属性注入时,首先得保证在类上,通过注解@PropertySource进行了属性文件注入,即
@PropertySource("classpath:properties/base.properties")
同时要声明org.springframework.context.support.PropertySourcesPlaceholderConfigurer,即
@Bean public static PropertySourcesPlaceholderConfigurer propertyConfig(){ return new PropertySourcesPlaceholderConfigurer(); }
g) 注入其它bean的属性
@Value("#{stu.name}") private String stuName;
h) 另外,还可以通过Enironment注入环境的所有内容(这包含了操作系统环境内容、自定义且加载进来的属性文件),即
@Autowired private Environment environment;
5、使用在bean中方法上的注解
a) @PostConstruct
在bean的构造函数执行完后执行
b) @PreDestory
在bean销毁之前执行
6、扫描声明bean的注解
a) @ComponentScan(包名)
通常注解在类上,扫描指定包,找出其中有bean声明(如@Service)的类,并进行注册。
四、设置环境的注解
1、@Profile
指定声明使用需要的环境条件,如@Profile("test")
2、@ActiveProfiles
指定激活的环境,如@ActiveProfiles("test")
3、@Conditional
条件注解,只有满足指定条件时,才追创建bean,
注意,使用此功能需要实现org.springframework.context.annotation.Condition接口,
并实现方法public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata)
如
实现Condition接口中的matches方法
public class WindowCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { return conditionContext.getEnvironment().getProperty("os.name").contains("Windows"); } }指定bean创建的条件
@Bean @Conditional(WindowCondition.class) public ListService windowListService(){ return new WindowListService(); }五、异步任务的注解
1、@EnableAsync
开启异步任务的支持,注意,同时配置类应实现接口org.springframework.scheduling.annotation.AsyncConfigurer,
并实现其中的方法getAsyncExecutor,声明异步任务线程池大小等信息,
实现其中的方法getAsyncUncaughtExceptionHandler,进行异常的处理,
如:
添加异步注解,及实现接口AsyncConfigurer
@EnableScheduling public class SpringAnnotationConfig implements AsyncConfigurer实现方法getAsyncExecutor
@Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(25); taskExecutor.initialize(); return taskExecutor; }实现方法getAsyncUncaughtExceptionHandler
@Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return null; }
2、@Async
注解在方法上,表明方法是异步的,注解在类上,表明整个类中的方法都是异步的
六、计划任务的注解
1、@EnableScheduling
开启计划任务的支持。
2、@Secheuled
声明计划任务,计划任务类型包括cron、fixDelay、fixRate等
a)cron按cron格式(cron是unix或类unix系统下的定时任务),指定时间点运行。如:
@Scheduled(cron = "0/3 * * ? * ?") public void cronExe(){ System.out.println(new Date()); }
b)fixRate
按固定频率执行任务,不管前一个任务执行是否执行完。如
@Scheduled(fixedRate = 2000) public void fixedRateExe(){ System.out.println(DateFormatUtils.format(new Date(),"HH-mm-ss"));
c)fixDelay
按固定延迟频率执行任务,即前一个任务执行完了,现延迟指定时间后,最后再执行
@Scheduled(fixedDelay = 2000) public void fixDelaExe(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(DateFormatUtils.format(new Date(),"HH-mm-ss")); }六、测试注解
1、@ContextConfiguration
指定测试的配置类,如
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringAnnotationConfig.class) @ActiveProfiles("dev") public class BaseTest {
2、@Test
测试方法,如
@Test public void baseTest() { System.out.println(config.getEnv()); }
3、@RunWith
spring text的测试驱动,发@RunWith(SpringJUnit4ClassRunner.class)
七、组合注解
1、通过注解定义的方式,可以将多个注解合成一个注解,效果就是只使用一个注解,便有多个注解的效果。
如
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Configuration @ComponentScan("com.dragon.springbootstudy") @EnableAspectJAutoProxy @PropertySource("classpath:properties/base.properties") @EnableAsync @EnableScheduling public @interface WiseConfig { String[] value() default {}; }之用便可以使用@WiseConfig注解配置类,等同于使用了多个注解
八、完整实例
1、主体配置类
@Configuration @ComponentScan("com.dragon.springbootstudy") @EnableAspectJAutoProxy @PropertySource("classpath:properties/base.properties") @EnableAsync @EnableScheduling public class SpringAnnotationConfig implements AsyncConfigurer { @Value("${myname}") private String myname; @Value("yes") private String flag; @Value("#{T(java.lang.Math).random()}") private double rand; @Value("#{systemProperties['os.name']}") private String osName; @Value("#{stu.name}") private String stuName; @Value("http://www.baidu.com") private Resource urlTxt; @Value("classpath:properties/base.properties") private Resource basePro; @Autowired private Environment environment; @Bean(name="stu") public Student student(){ Student stu = new Student(); stu.setName("panda"); return stu; } @Bean @Profile("dev") public Config devConfig(){ return new Config("dev"); } @Bean @Profile("test") public Config testConfig(){ return new Config("test"); } @Bean(name="simpleUtil") public SimpleUtil simpleUtil(){ return new SimpleUtil(); } @Bean @Conditional(WindowCondition.class) public ListService windowListService(){ return new WindowListService(); } @Bean @Conditional(LinuxCondition.class ) public ListService linuxListService(){ return new LinuxListService(); } @Bean public static PropertySourcesPlaceholderConfigurer propertyConfig(){ return new PropertySourcesPlaceholderConfigurer(); } public void outputResource() throws IOException { System.out.println("myname "+ myname); System.out.println("urlTxt: "+urlTxt); System.out.println("flag: "+flag); System.out.println("basePro: "+ IOUtils.toString(basePro.getInputStream())); System.out.println("urlTxt: "+ IOUtils.toString(urlTxt.getInputStream())); System.out.println("age "+environment.getProperty("age")); } @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(25); taskExecutor.initialize(); return taskExecutor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return null; } }2、aop配置类
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Action { String name() default ""; }
@Aspect @Component public class ActionHandler { @Before("@annotation(action)") public void beforeActionWork(JoinPoint joinPoint, Action action){ MethodSignature signature = (MethodSignature)joinPoint.getSignature(); Method method = signature.getMethod(); System.out.println("before method name "+ method.getName()); System.out.println("before name "+ action.name()); } @Around("@annotation(action)") public Object aroundAction(ProceedingJoinPoint pjp , Action action) throws Throwable { System.out.println("around name :"+ action.name()); String result = (String) pjp.proceed(); System.out.println("around result is :"+result); return null; } @After("@annotation(action)") public void afterActionWork(JoinPoint joinPoint,Action action){ MethodSignature signature = (MethodSignature)joinPoint.getSignature(); Method method = signature.getMethod(); System.out.println("after method name "+ method.getName()); System.out.println("after name "+ action.name()); System.out.println("after result "+ joinPoint); } }3、异步方法调用类
@Service public class ScheduleService { @Scheduled(fixedRate = 2000) public void fixedRateExe(){ System.out.println(DateFormatUtils.format(new Date(),"HH-mm-ss")); } @Scheduled(cron = "0/3 * * ? * ?") public void cronExe(){ System.out.println(new Date()); } @Scheduled(fixedDelay = 2000) public void fixDelaExe(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(DateFormatUtils.format(new Date(),"HH-mm-ss")); } }4、条件类
public class LinuxCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { return conditionContext.getEnvironment().getProperty("os.name").contains("Linux"); } }
5、最后运行main方法的类
public class SpringAnnotationMain { public static void main(String[] args) throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringAnnotationConfig.class); SpringAnnotationConfig config = context.getBean(SpringAnnotationConfig.class); config.outputResource(); // context.close(); } }