java部分常用注解

java常用注解

@Deprecated

当一个方法或者类已经弃用,新版本中将会有其他方法或者类可以代替这个使用,以后也不会再维护这个方法或类,就可以在方法的前面加上此注解,加上此注解方法名中间会如下图所示增加一条横线。

public class TestService {

	public static void main(String[] args) {
		new TestService().method();
	}
	
	/**
	 * 

Description: [do something]

*

created: 2019年4月26日上午9:51:09

* @param: * @return: void * @throws * {@link TestService} 链接替代类型或方法 */ @Deprecated public void method() { System.out.println("这是一个过时的方法"); } }

@Target

@Target用于声明注解可修饰的范围(即注解的使用范围),其注解中的ElementType属性可取以下值:
  * ONSTRUCTOR:用于描述构造器
  * FIELD:用于描述域
  * METHOD:用于描述方法
  * LOCAL_VARIABLE:用于描述局部变量
  * PACKAGE:用于描述包
  * PARAMETER:用于描述参数
  * TYPE:用于描述类、接口(包括注解类型) 或enum声明

@Target(ElementType.TYPE)
public @interface Table {
    /**
     * 数据表名称注解,默认值为类名称
     */
    public String tableName() default "className";
}

@Target(ElementType.FIELD)
public @interface NoDBColumn {

}

@Inherited

@Inherited 主要用于标记注解,被该注解标记过的注解,被认为是存在继承关系的。
即如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

@MapperScan

标注要扫描的mapper接口的位置,在使用mybatis时,通常使用@Mapper或@Repository标注dao层接口,但每个接口都进行标注比较繁琐,使用@MapperScan可以替代这一繁琐过程,只需在basePackages属性中配置接口所在的包名,即可在启动项目时扫描注入该包下的所有接口。

// 可指定多个包
@MapperScan(basePackages = {"com.company.project.dao"})

另外,在使用@MapperScan注解时,需要注意引入的注解类是否正确,通常情况下使用org的@MapperScan,但项目中如果使用了通用Mapper,那则使用tk的@MapperScan。

import org.mybatis.spring.annotation.MapperScan;
import tk.mybatis.spring.annotation.MapperScan;

@Ansyc

异步注解,标注的方法在调用时会单独创建一个线程去异步执行,下面贴上springboot中的简单使用示例:
 首先配置一个线程池:

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class ThreadPoolConfig {
	
	@Bean
	public Executor asyncExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(10);//核心线程数
		executor.setMaxPoolSize(200);//最大线程数
		executor.setQueueCapacity(99999);//线程队列大小
		executor.setThreadNamePrefix("thread-name:");//线程名前缀
 
		// rejection-policy:当pool已经达到max size的时候,如何处理新任务
		// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}
}

然后在启动类中开启异步调用:

@MapperScan(basePackages = {"com.myproject.demo.dao"})
@SpringBootApplication
@EnableAsync //开启异步注解
public class MyprojectApplication {
	public static void main(String[] args) {
		SpringApplication.run(MyprojectApplication.class, args);
	}
}

编写异步方法和测试方法

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class AsyncThreadUtil {

	@Async // 如果不指定名字,会使用缺省的“asyncExecutor”
	public void asyncTest(String name){
		for (int i = 0; i < 5; i++) {
			log.info(name + i);
			try {
				Thread.sleep(2L);
			} catch (InterruptedException e) {
				log.debug("sleep exception:{}", e.getMessage());
			}
		}
	}
}
-------------------测试方法------------------------
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.myproject.demo.util.AsyncThreadUtil;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyprojectApplicationTests {

	@Autowired
	private AsyncThreadUtil asyncThreadUtil;
	
	@Test
	public void contextLoads() {
		asyncThreadUtil.asyncTest(1 + "号张三");
		asyncThreadUtil.asyncTest(2 + "号张三");
	}
}

可以看到,在调用的异步方法开启了两个线程:thread-name:2、thread-name:1,并不是在主线程中处理的。

2019-04-28 11:40:40.346  INFO 6028 --- [           main] c.m.demo.MyprojectApplicationTests       : Started MyprojectApplicationTests in 8.785 seconds (JVM running for 10.128)
2019-04-28 11:40:40.849  INFO 6028 --- [  thread-name:2] com.myproject.demo.util.AsyncThreadUtil  : 2号张三0
2019-04-28 11:40:40.851  INFO 6028 --- [  thread-name:2] com.myproject.demo.util.AsyncThreadUtil  : 2号张三1
2019-04-28 11:40:40.853  INFO 6028 --- [  thread-name:2] com.myproject.demo.util.AsyncThreadUtil  : 2号张三2
2019-04-28 11:40:40.854  INFO 6028 --- [  thread-name:1] com.myproject.demo.util.AsyncThreadUtil  : 1号张三0
2019-04-28 11:40:40.855  INFO 6028 --- [  thread-name:2] com.myproject.demo.util.AsyncThreadUtil  : 2号张三3
2019-04-28 11:40:40.857  INFO 6028 --- [  thread-name:2] com.myproject.demo.util.AsyncThreadUtil  : 2号张三4
2019-04-28 11:40:40.858  INFO 6028 --- [  thread-name:1] com.myproject.demo.util.AsyncThreadUtil  : 1号张三1
2019-04-28 11:40:40.943  INFO 6028 --- [  thread-name:1] com.myproject.demo.util.AsyncThreadUtil  : 1号张三2
2019-04-28 11:40:40.958  INFO 6028 --- [  thread-name:1] com.myproject.demo.util.AsyncThreadUtil  : 1号张三3
2019-04-28 11:40:40.960  INFO 6028 --- [  thread-name:1] com.myproject.demo.util.AsyncThreadUtil  : 1号张三4

更多@Async异步线程使用方法,可以看看这篇博客:Spring中@Async用法详解及简单实例

@PostConstruct与@PreDestroy

从Java EE5规范开始,Servlet中增加了两个影响Servlet生命周期的注解,@PostConstruct和@PreDestroy,这两个注解被用来修饰一个非静态的void()方法。

被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

被@PreDestroy修饰的方法会在servlet执行destroy()方法执行之前执行。

@PostConstruct使用场景:
  如果想在生成对象时完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用,示例代码:

在这里插入代码片import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.myproject.demo.util.AsyncThreadUtil;

@Component
public class Demo {
	
	private Integer demoNumber;
	
	@Autowired
	private AsyncThreadUtil asyncThreadUtil;
	
	public Demo() {
	  //通过构造器去使用spring注入的属性是会失败的
	  //此处numberUtil为一个随意的bean,getNumber()获取 一个随机数,代码不贴了
		this.demoNumber = numberUtil.getNumber();
	}

	public Integer getDemoNumber() {
		return demoNumber;
	}

//	@PostConstruct
//	private void InitNumber() {
//		this.demoNumber = numberUtil.getNumber();
//	}
}
----------------以下是测试代码-------------------
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class MyprojectApplicationTests {
	@Autowired
	private Demo demo;
	
	@Test
	public void test2() {
		log.debug("demo number : {}", demo.getDemoNumber());
	}
	
}

最终的结果当然是失败的,因为当调用构造器时,其被spring管理的属性,还没有注入,导致了空指针异常,但当我们将上述代码中构造器中的代码注释掉,然后将@PostConstruct方法释放出来,再次执行,即可成功,达到我们想要的目的。
最后可以总结出,spring注入bean时的顺序为:Constructor >> @Autowired >> @PostConstruct

你可能感兴趣的:(java)