0、spring boot 回马枪
叫回马枪的一个原因也是希望读者对spring有过研究。在使用spring boot的时候碰到了很多注解,这让一直习惯使用xml配置形式开发的我着实脑壳疼,决定杀spring注解形式开发一个回马枪,各注解且报上名来,别以为穿上马甲我就不是认识你了。
1、注册组件
- @Configuration
标明这是一个配置类,以下注解均在该类中使用 - @Bean
注入bean 返回值就是bean配置中的class属性值,方法名或则默认value就是bean配置中的id属性值
@Configuration、@Bean 二将出马启动AnnoatationConfigApplicationContext在IOC容器中注入了一个bean ~ - @ComponentScan(value = “com.xxx.xxx”)
扫描包注解:常见@Repository、@Service、@Controller、@Component等
还可以使用@excludeFilter、@includeFilter花式指定过滤规则、正则表达式等来选择要扫描哪些包
xml形式:
<context:component-scan base-package="com.xxx.xxx">
- @Scope(“singleton”)
设置组件作用域
singleton:单实例(默认)
prototype : 多实例IOC启动的时候不会创建对象而是我们每次获取的时候才会创建
request : 同一次请求创建一个实例
session : 同一个session创建一个实例 @Lazy
针对singleton单实例的bean懒加载(延迟加载),容器启动的时候不创建对象,第一次获取bean的时候再进行初始化@Conditional({A.class,B.class,..})
按照条件注册:满住条件才给容器注册bean,A类B类得实现Condition接口
spring boot 底层大量使用的注解!可以注在类和方法上
一个例子:
以下代码解析:当环境中的系统是Windows的时候WindowsCondition类会返回true,则@Conditional({WindowsCondition.class})放行生成id=“bill”的bean;如果不是window系统则WindowsCondition类会返回false,则@Conditional({WindowsCondition.class})不会放行,导致不会创建被其注解的bean不会被创建。
//判断是不是linux系统的类,实现了Conditio接口
public class LinuxCondition implements Condition {
/**ConditionContext判断条件能使用的上下文环境
* AnnotatedTypeMetadata注解信息
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String osname = environment.getProperty("os.name");
if(osname.contains("Linux")) {
return true;
}
return false;
}
}
//判断是不是Windows系统的类
public class WindowsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//当前环境信息
Environment environment = context.getEnvironment();
String osname = environment.getProperty("os.name");
if (osname.contains("Windows")) {
return true;
}
return false;
}
}
在配置类@Condition中满足属性的情况下才注册bean
@Conditional({WindowsCondition.class})
@Bean("bill")
public Person person01() {
return new Person("Bill Gates",62);
}
@Conditional({LinuxCondition.class})
@Bean("linus")
public Person person02() {
return new Person("linus",48);
}
- @Import({A.class,B.class, …})
给容器注入bean的一种方式,常用导入第三方包的bean,用来快速导入需要的组件
使用上又有三种方式
- @Import({要注入的组件})
- ImportSelector接口:spring boot中常用,下面会写个例子
- ImporBeanDefinitionRegistrar接口
实现ImportSelect接口,返回连两个实体类(全类名)
public class MyImportSelector implements ImportSelector{
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.faby.bean.Blue","com.faby.bean.Yellow"};
}
}
配置导入,启动注解容器查看bean就能看到Blue和Yellow两个在存在容器中
@Configuration
@Import({MyImportSelector.class})
public class MainConfig {
}
- @FactoryBean
工厂形式注册bean
先实现FactoryBean定义工厂类,Color为我的bean
public class ColorFactoryBean implements FactoryBean<Color> {
public Color getObject() throws Exception {
return new Color();
}
public Class<?> getObjectType() {
return Color.class;
}
public boolean isSingleton() {
return true;
}
}
然后在配置类中注入工厂bean
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
2、生命周期-优先关注注解方式
1.@Bean(initMethod=”xxx”,destroyMethod=”xxx”)方式
//我的Bean类
public class Car {
public Car() {
System.out.println("------------car constructor");
}
public void myInit() {
System.out.println("------------car init");
}
public void myDestroy() {
System.out.println("------------car destroy");
}
}
//我的配置类中指定初始和销毁的方法
@Configuration
public class MainConfig {
@Bean(initMethod = "myInit",destroyMethod = "myDestroy")
public Car car(){
return new Car();
}
}
2.基于配置的时候可以使用以下方式来指定bean的创建方法和销毁方法
<bean id="" init-method="" destroy-mthod=""/>
3.让bean类实现InitializinBean和DisposableBean也可以实现管理bean生命周期
4.实现BeanPostProcessor后置处理器,spring的底层使用较多
5.@PostConstruct和@PreDestroy注解形式
@Component
public class Dog {
public Dog() {
System.out.println("-----------dog constructor");
}
@PostConstruct
public void init() {
System.out.println("-----------dog init");
}
@PreDestroy
public void destroy() {
System.out.println("-----------dog destroy");
}
}
3、属性赋值
- @value @PropertySource({“classpath:/xx/xx.properties”})
演示三种方式
public class Baby {
@Value("佩奇")//基本数值形式
private String name;
@Value("${xxx}")//取额配置文件环境变量得结合@PropertySource({"classpath:/xx/xx.properties"})
private String sex;
@Value("#{18-8}")//SpEl形式
private int age;
//get and set
}
4.自动装配
- @Autowired @Qualifier @Primary
我在service层中需要注入dao层的bean就可以使用@Autowired,但是会遇到一个问题,我不知道我的service中注入的是哪个dao类,那么我就可以用@Primary来指定一个首选的注入到service的bean,我也可以通过使用@Qualifier来选择我需要用到的bean来注入
样例代码,自动装配模式:
//service类
@Service
public class BookService {
@Autowired
private BookDao bookDao;
//get and set
}
//dao类
@Repository
public class BookDao {
}
默认首选装配模式,注入的bean就是被@primary修饰的bookDao2
//service类
@Service
public class BookService {
@Autowired
private BookDao bookDao;
//get and set
}
//dao类
@Repository
public class BookDao {
}
//我的配置类
@Primary
@Bean
public BookDao bookDao2() {
return new BookDao();
}
明确选择装配模式注入的bean就是被@Qualifier(“bookDao”)选着的的bookDao
//service类
@Service
public class BookService {
@Qualifier("bookDao")
@Autowired
private BookDao bookDao;
//get and set
}
//dao类
@Repository
public class BookDao {
}
//我的配置类
@Primary
@Bean
public BookDao bookDao2() {
return new BookDao();
}
- @Autowired可以标记在构造器、参数、方法、属性
1.参数位置
@Service
public class BookService {
private BookDao bookDao;
public void setBookDao(<font color=red>@Autowired</font> BookDao bookDao) {
this.bookDao = bookDao;
}
//get
}
2.标记在构造器上时如果组件只有一个有参构造器,这个参数构造器的@Autowire的可以省略
3.使用@Bean的时候方法传入了参数的 话也可以省略@Autowire
@Bean
public BookService bookService(BookDao bookDao) {
BookService bookService = new BookService();
bookService.setBookDao(bookDao);
return bookService;
}
- spring 还支持@Resource和@Inject等java规范的注解(我不想用┭┮﹏┭┮)