spring的注解开发
启动注解功能
启动注解功能
⚫ 启动注解扫描,加载类中配置的注解项
⚫ 说明:
◆ 在进行包所扫描时,会对配置的包及其子包中所有文件进行扫描
◆ 扫描过程是以文件夹递归迭代的形式进行的
◆ 扫描过程仅读取合法的java文件
◆ 扫描时仅读取spring可识别的注解
◆ 扫描结束后会将可识别的有效注解转化为spring对应的资源加入IoC容器
⚫ 注意:
◆ 无论是注解格式还是XML配置格式,最终都是将资源加载到IoC容器中,差别仅仅是数据读取方式不同
◆ 从加载效率上来说注解优于XML配置文件
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd">
<!--注解只是一个标记,如果spring不去扫描解析的话,这个标记就不会生效-->
<!-- 启动spring扫描注解的包,只扫描spring的注解--><context:component-scan base-package="com.fs"/></beans>
将类交给springIOC管理,bean的定义@Component @Controller @Service @Repository
代码解释
package com.fs.demo;
/*
spring注解将类交给spring的ioc管理*/import org.springframework.stereotype.Component;/*
@Component这个注解就相当于核心配置文件中的<bean id="类名首字母小写" class="权限定类名"/>@Component的衍生注解@Controller @Service @Repository,功能和 @Component一样只是spring对应三层结构来定的注解,功能一样,只是含义不同而已,所以使用其中那一个都可以将类交给ioc管理*/
@Component
public class AnnotationDemo {public AnnotationDemo() {System.out.println("AnnotationDemo被spring的IOC管理了~~~");}public void testMethod(){System.out.println("测试方法执行~~~");}
}
测试代码
@Testpublic void testOne(){//创建ioc容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//通过类名首字母小写从ioc中获取对象AnnotationDemo annotationDemo = (AnnotationDemo) applicationContext.getBean("annotationDemo");//使用类.class从ioc中获取对象AnnotationDemo bean = applicationContext.getBean(AnnotationDemo.class);//调用方法annotationDemo.testMethod();bean.testMethod();}
bean的作用域(@Scope(“单例或者双列”))(了解)
bean的生命周期
@Bean注解的使用
代码演示
package com.fs.demo;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*
@Configuration放在类上,说明这个类是一个spring的配置类首先这个类要标志是被spring扫描的,才会去扫描这个类下的其他注解@Bean*/
@Configuration
public class DataSourceDemo {/*在方法上@Bean将方法的返回值交给ioc管理配置DruidDataSource链接池对象交给ioc管理*/@Bean("druidDataSource")//给一个idpublic DruidDataSource getDruidDataSource(){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");druidDataSource.setUrl("jdbc:mysql://192.168.93.132:3306/test");druidDataSource.setUsername("root");druidDataSource.setPassword("root");return druidDataSource;}
}
测试代码
/*测试@Bean注入的druid连接池*/@Testpublic void testDataSource(){//创建ioc容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//通过类名首字母小写从ioc中获取对象DruidDataSource druidDataSource = (DruidDataSource) applicationContext.getBean("druidDataSource");
// DataSource dataSource = (DataSource) applicationContext.getBean(DataSource.class);DruidDataSource dataSource = applicationContext.getBean(DruidDataSource.class);
// System.out.println(dataSource);System.out.println(druidDataSource);}
bean的属性依耐注入DI
代码演示@Value
package com.fs.pojo;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
/*
@Value非引用类型的属性注入*/
@Component("student")//注入的时候起了个id名
//@Primary//没有起id的时候,这个注解是让这个bean优先加载
public class Student {/*@ValueDI依耐注入,给基本类型属性注入值*/@Value("18")private int age;@Value("小付")private String name;@Overridepublic String toString() {return "Student{" +"age=" + age +", name='" + name + '\'' +'}';}
}
代码演示@Autowired、@Qualifier
package com.fs.pojo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*
依耐注入之引用类型的注入@Autowired注意:注入的bean一定要在ioc容器中,才能注入因为这个注解是在ioc容器中去找对应的bean注入*/
@Component
public class Person{@Value("男")private String gender;/*@Autowired DI依耐注入按照类型自动注入(id类名首字母小写)*/
// @Autowired
// private Student student;/*@Autowired@Qualifier("student")//若有相同类型的,按照id注入*/@Autowired@Qualifier("student")private Student student;@Overridepublic String toString() {return "Person{" +"gender='" + gender + '\'' +", student=" + student +'}';}
}
测试代码
/*测试依耐注入属性@Autowired@Qualifier("id")*/@Testpublic void testDI(){//创建ioc容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//通过类名首字母小写从ioc中获取对象Person person = (Person) applicationContext.getBean("person");System.out.println(person);/*输出结果:Person{gender='男', student=Student{age=18, name='小付'}}*/}
了解注解
加载类路径下的properties文件@PropertySource
准备properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.93.132:3306/test
jdbc.username=root
jdbc.password=root
代码演示
package com.fs.properties;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;/*
@PropertySource
引入类路径下的的properties文件属性:value = "classpath:resource中的properties文件"*/
@Component//将这个类交给ioc管理
@PropertySource(value = "classpath:jdbc.properties")
public class PropertiesDemo {//@Value("${Key}")@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;@Overridepublic String toString() {return "PropertiesDemo{" +"driver='" + driver + '\'' +", url='" + url + '\'' +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
测试代码
/*测试@PropertySource(value = "classpath:jdbc.properties")测试引入类路径下的properties文件*/@Testpublic void testProperties(){//创建ioc容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//通过类名首字母小写从ioc中获取对象//PropertiesDemo propertiesDemo = (PropertiesDemo) applicationContext.getBean("propertiesDemo");//通过类名.classPropertiesDemo propertiesDemo = applicationContext.getBean(PropertiesDemo.class);System.out.println(propertiesDemo);//控制台输出结果:
//PropertiesDemo{driver='com.mysql.jdbc.Driver', url='jdbc:mysql://192.168.93.132:3306/test', username='root', password='root'}}
测底去除配置文件@Configuration、@ComponentScan @Import
我们现在还有applicationContext.xml这个文件,我们可以通过注解来指定一个配置类,从而让配置文件不见
@Import(类.class)配置类上写入后,就会把你给的类存放在IOC容器中,存放的id为类的全限定类名(包名加加类名)
代码演示
package com.fs.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*
@Configuration这个注解就表示这是一个配置类
@ComponentScan("com.fs")这个注解表示spring扫描那些包下的注解
@Import({DataSourceConfig.class})写在配置类,导入其他的配置类类.class就可以将这个类注入到spring的ioc容器中什么类都可以通过@Import({类.class,类2.class})来注入到spring的ioc容器中*/
@Configuration
@ComponentScan("com.fs")
@Import({DataSourceConfig.class})
public class SpringConfig {
}
测试代码
//使用spring配置类来创建ioc@Testpublic void testSpringConfig(){//创建ioc容器 AnnotationConfigApplicationContext(配置类.class)ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);//通过类名首字母小写从ioc中获取对象//PropertiesDemo propertiesDemo = (PropertiesDemo) applicationContext.getBean("propertiesDemo");//通过类名.classPropertiesDemo propertiesDemo = applicationContext.getBean(PropertiesDemo.class);System.out.println(propertiesDemo);}/*测试@Import 导入的druid连接池*/@Testpublic void testImport(){//创建ioc容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//通过类名首字母小写从ioc中获取对象DruidDataSource druidDataSource = (DruidDataSource) applicationContext.getBean("druidDataSource");
// DataSource dataSource = (DataSource) applicationContext.getBean(DataSource.class);DruidDataSource dataSource = applicationContext.getBean(DruidDataSource.class);
// System.out.println(dataSource);System.out.println(druidDataSource);}
依耐加载
依赖加载应用场景
⚫ @DependsOn
◆微信订阅号,发布消息和订阅消息的bean的加载顺序控制
◆双11活动期间,零点前是结算策略A,零点后是结算策略B,策略B操作的数据为促销数据。策略B
加载顺序与促销数据的加载顺序
⚫ @Lazy
◆程序灾难出现后对应的应急预案处理是启动容器时加载时机
⚫ @Order
◆多个种类的配置出现后,优先加载系统级的,然后加载业务级的,避免细粒度的加载控制