@Autowired @Resource @Qualifier及其他常用注解
一、@Autowired @Resource @Qualifier区别
ClientService 接口
public interface ClientService {
String client();
}
这里同时有2个类实现了该接口
ClientServiceImpl
@Service("ClientServiceImpl")
public class ClientServiceImpl implements ClientService {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Override
public String client() {
ServiceInstance si = loadBalancerClient.choose("eureka-client");
// 获取Application Service IP。192.168.1.1
System.out.println(si.getHost());
// 获取Ip及端口。192.168.1.1:8081
System.out.println(si.getInstanceId());
// 获取额外声明信息.{management.port=8081}
System.out.println(si.getMetadata());
// 端口 8081
System.out.println(si.getPort());
// 模式 null
System.out.println(si.getScheme());
// 应用程序名 eureka-client
System.out.println(si.getServiceId());
// URI http://192.168.1.1:8081
System.out.println(si.getUri().toString());
return null;
}
}
ClientServiceImpl2
@Service("ClientServiceImpl2")
public class ClientServiceImpl2 implements ClientService {
@Autowired
private RestTemplate restTemplate;
@Override
public String client() {
return restTemplate.getForObject("http://eureka-client/demo", String.class);
}
}
Controller类
@RestController
public class ClientController {
@Resource(name="ClientServiceImpl2")
private ClientService clientService;
@RequestMapping("/client")
public String client(){
return clientService.client();
}
}
这里先解释一下这些注解(这些注解可以相互替换)
@Controller 定义控制层Bean
@Service 定义业务层Bean
@Repository 定义DAO层Bean
@Component 定义Bean,不确定类型时
这里看一下这些注解的源码
这里解释一下什么时类型什么时名字
一般@Autowired和@Qualifier一起使用,@Resource单独用。
二、@AliasFor注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
/**
* 排除特定的自动配置类,这样它们将永远不会被应用。
* 比如我们有时候会排除掉数据库的自动配置
* @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
/**
* 排除特定的自动配置类名,这样它们将永远不会被应用。
* 例如:
* @SpringBootApplication(excludeName = {"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration", "org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration"})
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
/**
*用于扫描带注释组件的基本包。
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* 每个指定类的包将被扫描。
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
/**
* 用于处理{@code @SpringBootApplication}注释的扫描器应该
* 使用它继承的bean名称生成器,例如默认的
* {@link AnnotationBeanNameGenerator}或任何自定义实例提供给
* 在引导时的应用程序上下文。
*/
@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
/**
* 指定是否应该代理{@link Bean @Bean}方法来执行
* bean的生命周期行为,例如返回共享的单例bean实例
* 在用户代码中直接调用{@code @Bean}方法的情况。 该功能需要 方法拦截,通过运行时生成的CGLIB子类实现 有一些 限制,比如配置类和它的方法不是允许声明{@code final}。
* 默认值是{@code true},允许在配置类,以及外部调用该配置的 {@code @Bean}方法,例如,从另一个配置类。 如果 不需要的话因为每个特定配置的{@code @Bean}方法都是自包含和设计作为一个普通的工厂方法容器使用,开关这个标志为{@code false},以避免CGLIB子类处理。
*/
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
@SpringBootApplication并没有定义新的属性而是复用其他注解已有的注解属性并对其进行组合
形成新的注解从而到达到便捷的目的。这样的注解我们可以称之为复合注解。
所以在使用SpringBoot 时我们只需要@SpringBootApplication一个注解就能开启
自动配置,自动扫描的功能。
而不再需要使下面三个注解来达到同样的目的。
@Configuration
@ComponentSan
@EnnableAutoConfiguration
三、@Scope 定义Bean的作用域和生命过程
@Scope(“prototype”)
prototype | 解释 |
---|---|
singleton | 单例模式 全局有且仅有一个实例 |
prototype | 原型模式 – 每次获取Bean的时候会有一个新的实例 |
request | request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效 |
session | session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效 |
globalsession | global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义 |
public class People {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setid(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public People() {
}
public People(Integer id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "People{" +
"id=" + id +
", name='" + name + ''' +
'}';
}
public void initPeople(){
System.out.println("PeopleBean init");
}
public void destroyPeople(){
System.out.println("PeopleBean destroy");
}
}
@Configuration
public class RibbonConfig {
@Scope
@Bean(value="People1",name="People1",initMethod="initPeople",destroyMethod="destroyPeople")
public People getUser(){
System.out.println("创建People实例");
return new People(26,"lisi");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(RibbonConfig.class);
People people1 = (People)context.getBean("People1");
System.out.println(people1);
People people2 = (People)context.getBean("People1");
System.out.println(people2);
context.close();
}
}
结果
@PostConstruct
相当于init-method,使用在方法上,当Bean初始化时执行。
@PreDestroy
相当于destory-method,使用在方法上,当Bean销毁时执行。
修改
@PostConstruct
public void initPeople(){
System.out.println("PeopleBean init");
}
@PreDestroy
public void destroyPeople(){
System.out.println("PeopleBean destroy");
}
修改Bean
@Scope
@Bean(value="People1",name="People1")
public People getUser(){
System.out.println("创建People实例");
return new People(26,"lisi");
}
结果使一样的
四、总结
@Controller 定义控制层Bean
@Service 定义业务层Bean
@Repository 定义DAO层Bean
@Component 定义Bean,不确定类型时
其他三个注解继承Component 注解,其功能一样
一般@Autowired和@Qualifier一起使用,@Resource单独用。
@Autowired//默认按type注入
@Qualifier(“ClientServiceImpl2”)//一般作为@Autowired()的修饰用
@Resource(name=“ClientServiceImpl2”)//默认按name注入,可以通过name和type属性进行选择性注入
补充一个
@Inject 是JSR-330提供的 按类型装配,功能比@Autowired少,没有使用的必要。
@Scope(“prototype”)
值有:singleton,prototype,session,request,session,globalSession
@PostConstruct
相当于init-method,使用在方法上,当Bean初始化时执行。
@PreDestroy
相当于destory-method,使用在方法上,当Bean销毁时执行。