从Spring 3.x开始中有许多@EnableXXX的注解,例如@EnableWebMvc,@EnableAsync,@EnableCaching等待注解,这些注解的意义在于根据需要完成自动装配所需的bean。自动装配好比汽车的自动挡一样,它的实现大致分为两种方式,一种是通过自定义注解,另一种是实现相应的接口。
1.1 基于接口实现
一种是通过实现ImportSelector接口,另一种是实现ImportBeanDefinitionRegistrar接口。下面我们先看第一种实现方式。
package com.william.demo3;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/13 14:24
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MilkImportSelector.class)
public @interface EnableMilk {
Milk.Type type();
String name();
}
接口以及实现类
package com.william.demo3;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/15 16:26
*/
public interface Milk {
void processMilk();
void getMilk();
enum Type{
MENGNIU,
YILI
}
}
package com.william.demo3;
import org.springframework.stereotype.Component;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/15 21:45
*/
@Component
public class MengniuMilk implements Milk {
@Override
public void processMilk() {
System.out.println("加工蒙牛牛奶");
}
@Override
public void getMilk() {
System.out.println("获取蒙牛牛奶");
}
}
package com.william.demo3;
import org.springframework.stereotype.Component;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/15 21:44
*/
@Component
public class YiliMilk implements Milk {
@Override
public void processMilk() {
System.out.println("加工伊利牛奶");
}
@Override
public void getMilk() {
System.out.println("获取伊利牛奶");
}
}
实现ImportSelector接口
package com.william.demo3;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import java.util.Map;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/15 21:49
*/
public class MilkImportSelector implements ImportSelector{
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//获取EnableServer中所有的属性方法
Map annotationAttributes = annotationMetadata.getAnnotationAttributes(EnableMilk.class.getName());
Milk.Type type = (Milk.Type) annotationAttributes.get("type");
String [] importClassNames = new String[0];
switch (type){
case MENGNIU:
importClassNames = new String[]{MengniuMilk.class.getName()};
break;
case YILI:
importClassNames = new String[]{YiliMilk.class.getName()};
break;
}
return importClassNames;
}
}
测试类
package com.william.demo3;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/15 22:11
*/
@Configuration
@EnableMilk(type = Milk.Type.MENGNIU,name = "蒙牛")
public class EnableDemoMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(EnableDemoMain.class);
context.refresh();
Milk milk = context.getBean(Milk.class);
milk.processMilk();
milk.getMilk();
}
}
代码示例:github传送门
第二种实现ImportBeanDefinitionRegistrar接口,方式差不多:
package com.william.demo4;
import com.william.demo3.MilkImportSelector;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.StringUtils;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/15 25:19
*/
public class MilkImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
ImportSelector importSelector = new MilkImportSelector();
// String[] slecatedClassNames = importSelector.selectImports(annotationMetadata);
RootBeanDefinition beanDefinition=new RootBeanDefinition(importSelector.getClass());
String beanName= StringUtils.uncapitalize(importSelector.getClass().getSimpleName());
beanDefinitionRegistry.registerBeanDefinition(beanName,beanDefinition);
}
}
注解名改为@EnableNewMilk
package com.william.demo4;
import com.william.demo3.Milk;
import com.william.demo3.MilkImportSelector;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/13 14:24
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MilkImportBeanDefinitionRegistrar.class)
public @interface EnableNewMilk {
Milk.Type type();
String name();
}
测试类
package com.william.demo4;
import com.william.demo3.Milk;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
/**
* @Author: WilliamDream
* @Description:
* @Date: 2019/9/15 22:25
*/
@Configuration
@EnableNewMilk(type = Milk.Type.YILI,name = "伊利")
public class EnableRegisterDemoMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(EnableRegisterDemoMain.class);
context.refresh();
Milk milk = context.getBean(Milk.class);
milk.processMilk();
milk.getMilk();
}
}
代码示例:github传送门
1.2 基于注解方式实现
@Configuration
public class DataSourceConfiguration {
@Bean
public DataSource dataSource(){
return new DataSource();
}
}
public class DataSource {
private String driverClassName;
private String url;
private String username;
private String password;
//geter&seter略
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DataSourceConfiguration.class)
public @interface EnableDataSource {
}
//测试类
@EnableDataSource
public class EnableDatasourceMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//注册当前引导类(被@Configuration注解标注)到Spring上下文中
context.register(EnableDatasourceMain.class);
context.refresh();
//获取名为dataSource的bean对象
Object object = context.getBean("dataSource");
System.out.println(object);
context.close();
}
}
测试结果为:可以在控制台打印出DataSource对象实例。
相关代码示例:github传送门