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";
}

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域

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