Spring Framework 註解大全

Spring IOC/DI 相關注解

@Configuration
public class ApplicationConfig {
  //...
}

使用程序實現加載工廠

AnnotationConfigApplicationContext ctx= new AnnotationConfigApplicationContext(ApplicationConfig.class);

老版本編寫

<?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">
</beans>

使用程序實現加載工廠

ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
@Bean(name="date")
public Date getDate() {
		return new Date();
}

等價

<bean id="date" class="java.util.Date"</bean>

@Bean屬性介紹

屬性名 類型 是否必須 說明
name String 等價於<bean /> 的id屬性,不可以和value同時出現
value String 等價於<bean /> 的id屬性,不可以和name同時出現
autowire Bean 自動注入方式Autowire.NO/BY_NAME/BY_TYPE
destroyMethod String 等價於<bean /> 的destroy-method屬性
init-method String 等價於<bean /> 的init-method屬性

以上註解主要面向分層開發時候需要對不同層次的Bean分類管理。

@Service("userService")
public class UserService implements IUserService{

}
  • @ComponentScan

該註解用於掃描指定spring容器的bean,並且將掃描的bean放置到Spring工廠中。

@Configuration
@ComponentScan(basePackages="com.baizhi",
  excludeFilters= {
		@Filter(type=FilterType.ANNOTATION,value=Controller.class)
  },
  includeFilters= {
		  @Filter(Service.class),
		  @Filter(Repository.class)
  }
)
public class ApplicationConfig {
	//...
}

等價寫法

<context:component-scan base-package="com.baizhi">
        <context:include-filter 
               type="annotation"
                expression="org.springframework.stereotype.Repository,
                org.springframework.stereotype.Service"/>
        <context:exclude-filter 
         		type="annotation"
                expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
@Component("otherComponent")
@Scope(value=BeanDefinition.SCOPE_PROTOTYPE|SCOPE_SINGLETON)
public class OtherComponent {
	public OtherComponent() {
		// TODO Auto-generated constructor stub
	}
	@PostConstruct
	public void init() {
		System.out.println("init...");
	}
	@PreDestroy
	public void destory() {
		System.out.println("destory...");
	}
}

默認Spring工廠管理的Bean都是單例的,同時Spring會在工廠初始化的時候就創建配置的組件bean。這個時候如果想在工廠創建或者工廠消亡的時候執行某些方法時候,可以考慮添加@PostConstruct、@PreDestroy註解即可。

等價寫法

<bean id="otherComponent" class="com.baizhi.other.OtherComponent" 
          scope="prototype|singleton"
     	  init-method="init" 
     	  destroy-method="destory"/>
  • @Lazy

表示延遲spring工廠初始化Bean等價 beans標籤的default-lazy-init="true"屬性

@Configuration
@Lazy
public class ApplicationConfig {
  
}
  • @Autowired、@Resource、@Inject、@Qualifier、@Primary
@Bean(name="date1")
public Date getDate1() {
		return new Date();
}
@Bean(name="date2")	
public Date getDate2() {
	return new Date();
}
@Bean("date3")
public Date date(@Qualifier("date1")Date date) {
	System.out.println("000000000");
	return date;
}

@Bean管理的Bean的參數默認是自動注入的,此時如果發現有兩個相同類型的Bean出現就會導致注入失敗,解決之道是使用@Qualifier註解指定注入的參數當然也可以使用@Primary指定默認參與注入的類型。

@Bean(name="date1") 
@Primary
public Date getDate1() { 
  return new Date(); 
} 
@Bean(name="date2") 
public Date getDate2() { 
  return new Date(); 
} 
@Bean("date3") 
public Date date(Date date) { 
    System.out.println("000000000"); 
    return date; 
}

@Autowired和@Resource都是解決Spring的值注入的不同的是@Autowired按照類型注入,此時如果容器存在兩個相同類型的Bean組件的時候此時注入則是失敗的。這個時候需要和@Qulifier或者@Primary註解聯合使用解決類型衝突問題;@Resource註解是JDK1.6主持的註解該註解一旦指定name之後只會按照name注入如果沒有指定name屬性,先按照name注入如果查找不到再按照類型注入。@Inject和@Autowired用法一致但是使用@Inject需要導入額外的Maven依賴,而且如果存在類型衝突需要使用@Named註解指明需要注入的組件名字

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
  • @Required

該屬性用於作用在set方法上表明在初始化該Bean的時候,該set個方法的屬性必須設置值。一般和配置文件聯合使用

public class UserService implements IUserService{
	private Date date;
	public Date getDate() {
		return date;
	}
	@Required
	public void setDate(Date date) {
		this.date = date;
	}
}

配置文件

<context:annotation-config/>
<bean id="userService" class="com.baizhi.service.impl.UserService">
		<property name="date">
			<bean class="java.util.Date"></bean>
		</property>
</bean>	

注意必須配置context:annotation-config/屬性,否則@Required不起作用

  • @ImportResource(引入xml配置)
@Configuration
@ImportResource(value= {"classpath:applicationContext.xml"})
public class ApplicationConfig {
	
}
  • @Import(引入配置類)
@Configuration
public class ConfigA {
     @Bean
    public A a() {
        return new A();
    }
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
    @Bean
    public B b() {
        return new B();
    }
}
public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
// now both beans A and B will be available...
    A a = ctx.getBean(A.class);
    B b = ctx.getBean(B.class);
}
  • @Profile
@Configuration
@Import(value= {DevConfig.class,ProConfig.class})
public class ApplicationConfig {
	
}
-----------------------
@Configuration
@ImportResource(value= {"classpath:applicationContext.xml"})
@Profile("dev")
public class DevConfig {
	
}
-----------------------
@Configuration
@Profile("pro")
public class ProConfig {	
}

測試環境

AnnotationConfigApplicationContext ctx= new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("pro");
ctx.register(ApplicationConfig.class);
ctx.refresh();
		
System.out.println(ctx.getBean("userService"));
ctx.close();
  • @ImportResource(引入外部配置資源)
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;
    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(url, username, password);
    }
}

properties-config.xml

<beans>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>

jdbc.properties

jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root

@AspectJ相關注解

@AspectJ是一種aspects 的風格,它是用註釋註釋的常規Java類。

該註解用於開啓**@AspactJ**支持

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "com.baizhi")
public class AopConfig {
}

等價寫法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
        
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

@Aspect

該註解用於聲明切面類

@Aspect
@Component
public class AspectModule {
    
}

該註解用於聲明切入點

@Pointcut("execution(* com.baizhi..*.*(..))") // 切入點表達式
public void pc(){}

常用的切入點標誌符

切入點標誌符 說明
execution 匹配執行方法的連接點
within 限定匹配特定類型的連接點
this 用於指定AOP代理必須是指定類型的實例,用於匹配該對象的所有連接點
target 用於限定目標對象必須是指定類型的實例,用於匹配該對象的所有連接點
args 用於對連接點的參數類型進行限制,要求參數的類型時指定類型的實例
@annotation 用於對連接點的註解類型進行限制,要求註解的類型爲指定類型的實例

該註解用於聲明前置通知

@Aspect
public class AspectModule {
    @Pointcut("execution(* com.baizhi..*.*(..))")
    public void pc(){}
    
    // 參數爲切入點方法名(好處,定義一個切入點實現複用)
    @Before("pc()")
    // JoinPoint 用於獲取連接點信息(如獲取方法和類信息)
    public void before(JoinPoint joinPoint){ 
        System.out.println("-------------before advice-----------");
    }
}

老版本寫法

public class MyBeforeAdvice implements MethodBeforeAdvice{

    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("-------------before advice-----------");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.baizhi.service.UserServiceImpl"></bean>
    
    <bean id="beforeAdvice" class="MyBeforeAdvice"></bean>

    <aop:config>
        <aop:pointcut id="pc" expression="execution(* com.baizhi..*.*(..))"></aop:pointcut>
        <aop:advisor advice-ref="beforeAdvice" pointcut-ref="pc"></aop:advisor>
    </aop:config>
</beans>

該註解用於聲明匹配方法正常返回的後置通知

@AfterReturning("pc()")
public void afterReturning(){
    System.out.println("-------------after returning advice-----------");
}

正常返回
圖片
非正常返回

該註解用於聲明異常通知(目標方法產生異常執行的代碼片段)

@AfterThrowing("pc()")
public void afterThrowing(){
    System.out.println("-------------after throwing advice-----------");
}

切入方法拋出異常
圖片

該註解用於聲明後置通知(無論目標方法是否產生異常都會執行的代碼片段)

@After("pc()")
public void after(){
    System.out.println("-------------after advice-----------");
}

圖片

該註解用於聲明環繞通知(在調用目標方法前後執行)

@Around("pc()")
// 注意:參數ProceedingJoinPoint只能適用於環繞通知,用於獲取連接點信息
public void aroud(ProceedingJoinPoint pjp){
    System.out.println("-------------aroud advice start-----------");
    try {
        // 調用目標方法 並獲取目標方法返回值
        Object proceed = pjp.proceed();
    } catch (Throwable throwable) {
        throwable.printStackTrace();
    }
    System.out.println("-------------aroud advice end-----------");
}

該註解用於指定多切面執行順序(@Order值越小優先級越高)

@Aspect
@Component
@Order(1)
public class AspectModule {

    @Pointcut("execution(* com.baizhi..*.*(..))")
    public void pc(){}

    @Before("pc()")
    public void before1(JoinPoint joinPoint){
        System.out.println("------before1 advice first execute-----");
    }
}
@Aspect
@Component
@Order(5)
public class AspectModule1 {

    @Pointcut("execution(* com.baizhi..*.*(..))")
    public void pc(){}
    
    @Before("pc()")
    public void before2(JoinPoint joinPoint){
        System.out.println("------before2 advice second execute-----");
    }
}

老版本寫法

<aop:config>
    <aop:pointcut id="pc" expression="execution(* com.baizhi..*.*(..))"></aop:pointcut>
    <aop:advisor advice-ref="beforeAdvice1" pointcut-ref="pc" order="1"></aop:advisor>
    <aop:advisor advice-ref="beforeAdvice2" pointcut-ref="pc" order="5"></aop:advisor>
</aop:config>

Spring MVC相關注解

該註解用於開啓基於註解的MVC支持

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.baizhi")
public class WebMvcConfig extends WebMvcConfigurerAdapter {
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		// TODO Auto-generated method stub
		registry.addResourceHandler("/**")
		.addResourceLocations("/")
		.setCachePeriod(1000000);
	}
}

老版本寫法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

啓動引導類


/**
 * @author gaozhy
 * @date 2018/4/8.11:18
 */
public class WebInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(MvcConfig.class);
        ctx.setServletContext(servletContext);

        ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
    }
}

該註解指示特定的類充當控制器的角色

@Controller
public class HelloController {
    
}

該註解爲組合註解@Controller@ResponseBody(控制器實現REST API,響應JSON、XML或自定義的MediaType內容。無需用@ResponseBody註釋所有的@RequestMapping方法。),用於構建Restful風格的控制器類

@RestController
public class RestfulController {

}
@RequestMapping(value = "/",method = RequestMethod.GET)
public String index(){
    return "Hello World";
}

以下註解用於簡化HTTP方法的映射,並更好地表達帶註釋的處理程序方法的語義。例如,@GetMapping 等同於@RequestMapping(method = RequestMethod.GET)

@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

該註解放在方法參數前,用於綁定URL中攜帶的Value

/**
 * 例如:http://localhost:8080/owners/1
 */
@GetMapping("/owners/{ownerId}")
@ResponseBody
public String findOwner(@PathVariable String ownerId) {
    System.out.println(ownerId);
    return ownerId;
}

用法一:應用在普通方法上
@ModelAttribute 註解的方法會在Controller每個目標方法執行之前都執行(注:對於一個Controller中包含多個URL的時候,要謹慎使用),並且會將返回值自動存儲到Model中(key默認爲首字母小寫的返回值名,value爲方法返回值)

/**
 * 例如:http://localhost:8080/owners/1
 */
@GetMapping("/owners/{ownerId}")
@ResponseBody
public String findOwner(@PathVariable String ownerId) {
    System.out.println(ownerId);
    return ownerId;
}

@ModelAttribute
public User getUser(){
    System.out.println("----------進入到 getUser method----------");
    return new User(1,"張三");
}

@ModelAttribute
public Person getPerson(){
    System.out.println("----------進入到 getPerson method----------");
    return new Person(1,"李四","北京");
}

在請求http://localhost:8080/owners/1,會依次訪問getUser、getPerson,然後再去訪問目標方法findOwner,被@ModelAttribute註解的方法的返回值會自動添加到Model中保存起來。

類似於

@GetMapping("/owners/{ownerId}")
@ResponseBody
public String findOwner(@PathVariable String ownerId,Model model) {
    model.addAttribute("user",new User(1,"張三"));
    model.addAttribute("person",new Person(1,"李四","北京"));
    System.out.println(ownerId);
    return ownerId;
}
  • 用法二:應用在方法的參數上

將Model中Key對應的Value綁定給指定參數

@ModelAttribute
public User getUser(){
    System.out.println("----------進入到 getUser method----------");
    return new User(1,"張三");
}

@ModelAttribute
public Person getPerson(){
    System.out.println("----------進入到 getPerson method----------");
    return new Person(1,"李四","北京");
}

@GetMapping("/test")
@ResponseBody
public String test(@ModelAttribute("user")User user,@ModelAttribute("person")Person person) {

    System.out.println(user);
    System.out.println(person);

    return "test ok";
}

該註解使用在類上,用於將Model中的數據保存到HttpSession中(跨請求傳遞數據)

屬性名 說明
value 指定存放到Session域中Model的key的鍵名
type 指定存放到Session域中Model的value的類型
@Controller
@SessionAttributes(value={"name"},types = Integer.class)
public class HelloController {

    @RequestMapping("/test1")
    public String test1(Model model){
        System.out.println("--------------test1-----------------");
        model.addAttribute("name","zs");
        model.addAttribute("age",18);
        model.addAttribute("sex","male");
        return "redirect:test2";
    }

    @RequestMapping("/test2")
    @ResponseBody
    public String test2(ModelMap modelMap, SessionStatus sessionStatus){
        System.out.println("--------------test2-----------------");
        System.out.println(modelMap.get("name") + " | "+ modelMap.get("age")+ " | "+modelMap.get("sex"));
        // 清除Session中保存的數據
        sessionStatus.setComplete();
        return "test2 ok";
    }
}

該註解用於將Session中key對應的value綁定給指定參數

@RequestMapping("/test3")
@ResponseBody
public String test3(@SessionAttribute("name") String name,@SessionAttribute("age") Integer age){
    System.out.println("--------------test3-----------------");
    System.out.println(name + " | " + age);
    return "test3 ok";
}

該註解用於將Request中key對應的value綁定給指定參數

@RequestMapping("/test4")
@ResponseBody
public String test4(@RequestAttribute("sex")String sex){
    System.out.println("--------------test4-----------------");
    System.out.println(sex);
    return "test4 ok";
}

該註解用於綁定請求參數給控制器方法指定參數

// http://localhost:8080/test5?id=1&name=zs
@RequestMapping("/test5")
@ResponseBody
public String test5(@RequestParam("id") Integer id,@RequestParam("name") String username){
    System.out.println("--------------test5-----------------");
    System.out.println(id + " | " + username);
    return "test5 ok";
}

該註解用於將請求頭中參數綁定給控制器指定方法參數

@RequestMapping("/test6")
@ResponseBody
public String test6(@RequestHeader Map requestHeaderMap){
    System.out.println("--------------test6-----------------");
    requestHeaderMap.forEach((k,v) -> System.out.println(k + " | " +v));
    return "test6 ok";
}

注:在上面的案列中,請求頭中所有數據會以key-value的方式存放到Map集合中,也可以使用 @RequestHeader(“Accept-Encoding”) 這樣的方式,獲取特定信息。

該註解用於將Cookie中的value綁定給控制器指定方法參數

@RequestMapping("/test7")
@ResponseBody
public String test7(@CookieValue("JSESSIONID") String jessionId){
    System.out.println("--------------test7-----------------");
    System.out.println(jessionId);
    return "test7 ok";
}

該註解用於將請求主體通過HttpMessageConverter讀取和反序列化爲對象

@PostMapping("/test8")
@ResponseBody
public String test8(@RequestBody User user){
    System.out.println(user);
    return "test8 ok";
}

該註解用於將方法返回值通過HttpMessageConverter序列化到響應體

該註解用於支持跨越請求處理

@PostMapping("/test10")
@ResponseBody
@CrossOrigin(origins = "http://192.168.31.187:8080",maxAge = 1800)
public String test10(String name,Integer id){
    System.out.println(name + " | " + id);
    return "test10 ok";
}

瀏覽器從一個域名的網頁去請求另一個域名的資源時,域名、端口、協議任一不同,都是跨域

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章