1. 程式人生 > 實用技巧 >@Autowired 引發的一系列思考

@Autowired 引發的一系列思考

關於Java註解

註解定義

  1. 標記註解 - 沒有元素
@interface Marker {
}
  1. 單元素註解 - 只有一個元素
@interface Single {
String value() default "name";
}
  1. 普通註解 - 除了上面兩種
@interface Normal {
String id();
String name();
} @interface NormalWithValue {
String id() default "id";
String value();
}

註解使用

1. 標記註解 由 @Marker() 可以簡化為 @Marker
2. 按照約定,單元素註解的名稱定義為 value ,這樣 Single(value="123") 可以簡化為 @Single("123")
3. 對於普通註解,必須給出註解中名稱以及對應的值,當然有預設值的除外,如果普通註解含有 value 名稱,並且其他名稱都有預設值,也可以簡化為 @Normal("123")

例項如下:

@Marker
@Single("123")
@Normal(id = "123", name = "123")
@NormalWithValue("123")
class AnnotationMain {
}

Annotation Types

Annotations

Spring 中的註解

  1. 元註解(Meta-Annotations)
在另一個註解上宣告的註解,所以說任何一個註解都可以成為元註解

在下面這個例子中,@Target、@Retention、@Documented、@Indexed都是元註解
如果@Component又跑到別的註解頭上了,那它也是元註解 @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
}
  1. 角色註解(Stereotype Annotations)
代表著一種固有的形象
比如@Component代表元件,@Repository代表DAO,@service代表服務等等
  1. 組合註解(Composed Annotations)
將一個或多個註解註解到一個註解上
在Spring中,註解上的任何一個註解都是可以被感知到的,就代表這個註解擁有了上述幾個註解的所有功能 在下面這個例子中,@EnableAutoConfiguration組合了@AutoConfigurationPackage和@Import
使用@EnableAutoConfiguration的類會被Spring認為@EnableAutoConfiguration和@AutoConfigurationPackage也是存在的
因此@EnableAutoConfiguration就具備了@AutoConfigurationPackage的功能以及@Import的功能
這個實現好像是通過快取實現的,具體也不太瞭解,有大佬知道的可以在評論裡告知一下~ @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}

Spring-Annotation-Programming-Model

MergedAnnotation-API-internals

Spring中的 @Autowired,一個自動注入的註解

  1. 可以在建構函式中注入
@Service
@Getter
public class MyService1 {
private MyDao1 myDao1; @Autowired
public MyService1(MyDao1 myDao1) {
this.myDao1 = myDao1;
}
}
  1. 可以在方法中注入
Spring 會自動自動執行方法,並把myDao注入住到方法引數裡面

@Getter
public class MyService2 {
private MyDao1 myDao1;
private MyDao2 myDao2; @Autowired
public void setMyDao1(MyDao1 myDao1) {
this.myDao1 = myDao1;
} @Autowired
public void fun(MyDao2 myDao2) {
this.myDao2 = myDao2;
}
}
  1. 也可以在屬性上注入
@Getter
public class MyService3 {
@Autowired
private MyDao1 myDao1;
}
  1. 也可以混合注入
@Getter
public class MyService4 {
@Autowired
private MyDao1 myDao1;
private MyDao2 myDao2;
private MyDao3 myDao3; @Autowired
public void fun(MyDao2 myDao2) {
this.myDao2 = myDao2;
} @Autowired
public MyService4(MyDao3 myDao3) {
this.myDao3 = myDao3;
}
}
  1. 其他注意的地方
  • 使用@Autowired時,容器裡必須要存在這個型別的例項的,如果沒有就會報錯,如果不是必須要注入此類,可以將required設定為false,預設為true
@Getter
public class MyService5 {
private MyDao1 myDao1; @Autowired(required = false)
public MyService5(MyDao1 myDao1) {
this.myDao1 = myDao1;
}
}
  • 如果在多個建構函式上使用@Autowired,則所有的@Autowired必須將required設定為false,將會選一個引數較多的建構函式進行注入
@Getter
public class MyService6 {
private MyDao1 myDao1;
private MyDao2 myDao2; @Autowired(required = false)
public MyService6() {
} @Autowired(required = false)
public MyService6(MyDao1 myDao1) {
this.myDao1 = myDao1;
} @Autowired(required = false)
public MyService6(MyDao2 myDao2) {
this.myDao2 = myDao2;
}
}
  • 如果只有一個建構函式,不用加@Autowired也會自動注入,下面的例子中的所有屬性將會注入
@Getter
public class MyService6 {
private MyDao1 myDao1;
private MyDao2 myDao2; public MyService6(MyDao1 myDao1, MyDao2 myDao2) {
this.myDao1 = myDao1;
this.myDao2 = myDao2;
}
}

beans-autowired-annotation

使用Java程式設計獲取Spring bean

  • @Bean 用於標記一個bean 定義
  • @Configuration 裡面有很多 @Bean 標記的方法
public class MyDao {
} @Getter
@AllArgsConstructor
@NoArgsConstructor
public class MyService {
private MyDao myDao;
} @Configuration
public class AppConfig { @Bean
public MyService myService(MyDao myDao) {
return new MyService(myDao);
} @Bean
public MyDao myDao() {
return new MyDao();
}
} public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = applicationContext.getBean(MyService.class);
MyDao myDao = applicationContext.getBean(MyDao.class);
System.out.println(myService.getMyDao() == myDao);
}
}
輸出:
true
說明 myService不為null,myDao不為null,myDao已經被注入到myService中