安裝apk 安裝APK(filePath) lua源碼 function 安裝APK(filePath) local intent = Intent(Intent.ACTION_VIEW); intent.addCategory("android.intent.category.DEFAULT"); ...
1.@Bean與@Configuration
(1) 標註於類之上的@Configuration註解與標註於方法之上的@Bean註解是支持基於Java的容器配置的核心,被@Bean註解標註的方法用於實例化bean並將其註入至容器中,它與基於xml配置中的<bean/>標簽起著相同的作用,@Bean可用在任何被@Component註解標註的類中,不過絕大部分情況下它們都被用於被@Configuration註解標註的類中;被@Configuration註解標註的類通常作為bean的定義源,如同基於xml配置中的<beans/>標簽,此外,還可在@Configuration標註的類中配置bean之間的依賴關係,如下
//兩個普通的類,其中ExampleB依賴ExampleA
public class ExampleA { }
public class ExampleB {
private ExampleA exampleA;
public ExampleB(ExampleA exampleA) {
this.exampleA = exampleA;
}
}
//配置類
@Configuration
public class Config {
//註入bean ExampleA
@Bean
public ExampleA exampleA() {
return new ExampleA();
}
//調用exampleA()方法來配置ExampleB
@Bean
public ExampleB exampleB() {
return new ExampleB(exampleA());
}
//上下這兩個exampleB方法等價,註意,在下麵這個例子中,Spring會自動幫我們註入ExampleA對象
// @Bean
// public ExampleB exampleB(ExampleA exampleA) {
// return new ExampleB(exampleA);
// }
}
//啟動容器,列印註入的對象是否相同
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
System.out.println(ctx.getBean(ExampleB.class).getExampleA() == ctx.getBean(ExampleA.class));
//觀察結果,可見Spring執行了依賴註入,註入了容器中的ExampleA,而非new出來了一個新的ExampleA
true
(2) @Bean也可用在任何被@Component註解標註的類中,此時,我們稱其為lite @Bean模式,而在這種lite模式下,我們不能配置bean之間的依賴關係,如下所示
//取上面的例子,其他保持不變,只將Config類上的@Configuration註解變更為@Component註解,此時其中的@Bean註解就處於lite @Bean模式
@Component
public class Config {
//保持不變...
}
//啟動容器,觀察列印結果,為false,可見此時Spring並沒有執行依賴註入,而是直接new出來了一個新的ExampleA給ExampleB,因此在這種lite模式下,我們不能配置bean之間的依賴關係
2.通過AnnotationConfigApplicationContext實例化Spring容器
(1) AnnotationConfigApplicationContext作為Spring的容器,它不僅可以接受@Configuration類(同時這個類本身也會被註冊為一個bean)作為參數,還可以接受@Component類或用JSR-330註解標註的類作為參數,如下
//例一: 一個Spring配置類
@Configuration
public class Config {
}
public static void main(String[] args) {
//使用@Configuration類作為輸入,完全擺脫掉基於xml的配置
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
//列印,會觀察到Config也被註入到了容器中
Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);
}
//例二: ExampleB被JSR 330標準註解標註
@Component
public class ExampleA {
}
@Named
public class ExampleB {
@Inject
private ExampleA exampleA;
public ExampleA getExampleA() {
return exampleA;
}
}
public static void main(String[] args) {
//使用@Component類或用JSR-330註解標註的類作為參數,容器會對它們進行依賴註入
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ExampleA.class, ExampleB.class);
System.out.println(ctx.getBean(ExampleB.class).getExampleA());
}
(2) 可以使用AnnotationConfigApplicationContext類的register(Class<?>…)方法編程式的向容器中註冊,如下
public class ExampleA { }
public static void main(String[] args) {
//使用無參構造函數
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
//編程式的向容器中註冊bean ExampleA
ctx.register(ExampleA.class);
//refresh()方法用於處理bean,一定要調用此方法,否則容器將拋出異常
ctx.refresh();
System.out.println(ctx.getBean(ExampleA.class));
}
(3) 我們可以使用@ComponentScan(basePackages = "...")註解或<context:component-scan base-package="..."/>標簽來開啟註解掃描,此外,AnnotationConfigApplicationContext也提供了scan(String…)方法來開啟註解掃描,如下
//ExampleA位於cn.example.spring.boke包下
@Component
public class ExampleA { }
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
//開啟註解掃描,掃描cn.example.spring.boke"包下的bean
ctx.scan("cn.example.spring.boke");
ctx.refresh();
System.out.println(ctx.getBean(ExampleA.class));
}
(4) 在web環境中,可以使用AnnotationConfigWebApplicationContext,來配置ContextLoaderListener監聽器或DispatcherServlet,具體配置細節可參考官方文檔
3.使用@Bean註解
(1) @Bean註解是一個方法級別的註解,類似於基於xml配置中的<bean/>標簽,我們可以在@Configuration類或@Component類中使用該註解,它常用於聲明一個bean,如下
@Configuration
public class Config {
//@Bean註解用於將方法的返回值註冊為容器中的一個bean,方法返回類型就是該bean的類型,預設情況下,方法名就是bean的名稱
//下麵這個例子:向容器中註入一個類型為ExampleA,名稱為exampleA的bean
@Bean
public ExampleA exampleA() {
return new ExampleA();
}
}
(2) 針對@Bean方法的返回類型,也有些細節需要註意,如下所示
//有兩個介面A和B
public interface A { }
public interface B { }
//ExampleA實現了這兩個介面
public class ExampleA implements A, B { }
//而另一個bean ExampleB,它依賴了類型為B的bean
@Component
public class ExampleB {
@Autowired
private B b;
public B getB() {
return b;
}
}
//配置類
@Configuration
@ComponentScan(basePackages = "cn.example.spring.boke")
public class Config {
//註意,我們返回了ExampleA的實例,不過卻將返回類型聲明為了A
@Bean
public A exampleA() {
return new ExampleA();
}
}
//接著,啟動容器,會發現容器拋出NoSuchBeanDefinitionException: No qualifying bean of type 'cn.example.spring.boke.B'的異常,可見容器將返回的ExampleA僅視作了A類型然後就用於註入,雖然它也可以被視作B類型
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
System.out.println(ctx.getBean(ExampleB.class).getB());
//針對上面的情況,有兩種辦法解決:
//方法一:最直接,直接返回類型B而非A,如下
@Bean
public B exampleA() {
return new ExampleA();
}
//方法二:其他的不變,只在我們的ExampleB上,加上@Lazy註解,讓容器有時間去充分的識別ExampleA,使它意識到ExampleA還可以視作B類型
@Component
@Lazy
public class ExampleB {
//省略...
}
(3) @Bean方法可以擁有任意數量的參數,這些參數就是這個bean的依賴項,如下
@Configuration
public class Config {
@Bean
public ExampleB exampleB() {
return new ExampleB();
}
//ExampleA依賴了ExampleB,Spring會為我們自動註入容器中的這個ExampleB對象,類似於基於構造函數的依賴註入
@Bean
public ExampleA exampleA(ExampleB exampleB) {
return new ExampleA(exampleB);
}
}
(4) 同普通的bean,由@Bean方法註入的bean也支持由JSR-250所定義的生命周期回調註解,支持InitializingBean,DisposableBean或Lifecycle等介面,支持各種Aware介面用於註入容器內置組件,同時@Bean還提供了initMethod和destroyMethod屬性用於配置初始化和銷毀回調,同<bean/>標簽的屬性,如下
public class ExampleA implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@PostConstruct
public void init() {
System.out.println("init...");
}
public void destroy() {
System.out.println("destroy...");
}
}
@Configuration
public class Config {
@Bean(destroyMethod = "destroy")
public ExampleA exampleA() {
return new ExampleA();
}
}
(5) 預設情況下,當我們使用基於Java的配置來定義一個bean的時候,如果在這個bean中有聲明public修飾的close或shutdown方法,那麼這些方法會隨著該bean的銷毀回調的觸發而同時被調用,這是Spring提供的一個預設機制,無需任何的配置都會生效,但如果我們想關閉掉這一機制,可通過設置@Bean中的屬性destroyMethod=""來達到這一目的,如下
//設置destroyMethod = "",禁用掉Spring會自動觸發public修飾的close或shutdown方法的機制
@Bean(destroyMethod = "")
public ExampleA exampleA() {
return new ExampleA();
}
(6) 我們可以通過使用@Scope註解來指定bean的作用域,如下
@Configuration
public class Config {
//由@Bean方法所聲明的bean的作用域預設為singleton
//@Scope註解還可用於類上
@Bean
@Scope("prototype")
public ExampleA exampleA() {
return new ExampleA();
}
}