Spring是简化j2ee开发的一个框架,通过指定id、类名配置bean虽然简单,但是当bean很多的时候,spring的配置文件会过于臃肿,使用注解技术配置bean使配置更加简介。
注解配置bean的原理是组件扫描,通过在spring配置文件中定义包扫描器,spring就能从classpath下自动扫描、侦测和实例化具有特定注解的bean。
Spring注解有以下四个,位于org.springframework.stereotype
目录下。
Component
基本注解,标识了一个受Spring管理的组件,源码如下:
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
String value() default "";
}
Repository
标识持久层组件,源码如下:
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
String value() default "";
}
Service
标识业务层组件
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
String value() default "";
}
Controller
标识表现层组件
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
String value() default "";
}
配置bean的步骤:
Spring有一个默认的bean命名策略:使用非限定类名,第一个字母小写,或者通过value属性设置。举例,一个UserService类,通过Service注解标准了:
package com.stuspring.annbeans.service;
import org.springframework.stereotype.Service;
/** * Created by bee on 17/5/4. */
@Service
public class UserService {
public void add(){
System.out.println("UserService add..");
}
}
在Spring的配置文件中定义组件扫描器(注意引入context命名空间):
<?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: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/spring-context-4.3.xsd">
<context:component-scan base-package="com.stuspring.annbeans" />
</beans>
现在Bean已经可以使用了,它的id就是类名UserService首字母小写,即userService。获取bean并调用add方法:
package com.stuspring.annbeans;
import com.stuspring.annbeans.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/** * Created by bee on 17/5/4. */
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
UserService userService = (UserService) ctx.getBean("userService");
System.out.println(userService);
userService.add();
}
}
打印结果:
com.stuspring.annbeans.service.UserService@c81cdd1
UserService add..
可以通过value属性来设置bean的id,代码如下,这样bean的id就改为uService了。
@Service("uService")
public class UserService {
public void add(){
System.out.println("UserService add..");
}
}
<context:component-scan >
可以定义一些属性及配置:
如果仅需要扫描特定的类而不是基类包下的所有类,可以使用resource-pattern属性过滤特定的类。例如:
<context:component-scan base-package="com.stuspring.annbeans" resource-pattern="repository/8.class"/>
<context:exclude-filter>
子节点表示排除在外的目标类
<context:include-filter>
子节点表示要包含的目标类在UserController类中创建一个UserService对象:
@Controller
public class UserController {
private UserService userService;
public void execute(){
System.out.println("UserController execute...");
userService.add();
}
}
这时候获取UserController对象:
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
UserController userController = (UserController) ctx.getBean("userController");
userController.execute();
}
}
运行会报空指针异常:
Exception in thread "main" java.lang.NullPointerException
at com.stuspring.annbeans.controller.UserController.execute(UserController.java:18)
at com.stuspring.annbeans.Main.main(Main.java:15)
UserController execute...
从打印结果中可以看出UserService在UserController类中没有被标准。<context:component-scan>
元素会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired、@Resource、@Inject注解的属性。
在UserService对象上添加注解@Autowired:
@Autowired
private UserService userService;
这样UserService对象就会自动装配上。
@Autowired注解会自动装配具有兼容类型的单个Bean属性: