@Autowired 引發的一系列思考
阿新 • • 發佈:2020-07-08
關於Java註解
註解定義
- 標記註解 - 沒有元素
@interface Marker {
}
- 單元素註解 - 只有一個元素
@interface Single {
String value() default "name";
}
- 普通註解 - 除了上面兩種
@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 {
}
Spring 中的註解
- 元註解(Meta-Annotations)
在另一個註解上宣告的註解,所以說任何一個註解都可以成為元註解
在下面這個例子中,@Target、@Retention、@Documented、@Indexed都是元註解
如果@Component又跑到別的註解頭上了,那它也是元註解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
}
- 角色註解(Stereotype Annotations)
代表著一種固有的形象
比如@Component代表元件,@Repository代表DAO,@service代表服務等等
- 組合註解(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
,一個自動注入的註解
- 可以在建構函式中注入
@Service
@Getter
public class MyService1 {
private MyDao1 myDao1;
@Autowired
public MyService1(MyDao1 myDao1) {
this.myDao1 = myDao1;
}
}
- 可以在方法中注入
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;
}
}
- 也可以在屬性上注入
@Getter
public class MyService3 {
@Autowired
private MyDao1 myDao1;
}
- 也可以混合注入
@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;
}
}
- 其他注意的地方
- 使用
@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;
}
}
使用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中