spring注解开发
😁一、组件注册
🍎一、给容器中注册组件
创建一个java类
@Configuration
: 说明这是一个配置类
@Bean
: 给容器中注册一个bean对象
@Configuration
publi class MyConfig{
@Bean("per") // 如果不设置获取到的是方法的方法名,如果设置需要获取的就是设置的名称
public Person person(){
return new Person("张三", 23);
}
}
测试类
public class MyTest{
@Test
public void testConfig(){
// 通过读取注解配置获取容器对象
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
Person person = context.getBean(Person.class);
System.out.println(person);
// 获取到所有的bean容器对象实例
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
}
}
}
🍊二、自动扫描组件
@ComponentScan
相当于配置文件的context component-scan base-package=""
属性
excludeFilters
: 设置要排除的规则
@ComponentScan(value="", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = {Controller.class, Service.class})})
设置排除的规则为注解类型,排除的注解为@Controller和@Service的类文件
includeFilters
: 设置要包含的规则,使用方法类似excluedeFilters,但是作用正好相反
@Configuration
@ComponentScan("com.wyxz.spring")
public class MyConfig{
@Bean
public Person person() {
return new Person("张三", 23);
}
}
测试
public class MyTest{
@Test
public void testConfig(){
// 获取到所有的bean容器对象实例
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
}
}
}
@ComponentScans
可以配置多个@componentScan
自定义TypeFilter
过滤规则
public class MyTypeFilter implements TypeFilter {
/**
*
* @param metadataReader 读取到当前正在扫描的类的信息
* @param metadataReaderFactory 可以获取到其他任何类的信息
* @return
* @throws IOException
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// 获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// 获取当前类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取当前类的资源
Resource resource = metadataReader.getResource();
// 获取到当前类的名称
String className = classMetadata.getClassName();
return false;
}
}
在配置类的@ComponentScan中的Filter中的class属性中
@ComponentScan(value="", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = {Controller.class, Service.class, MyTypeFilter.class})})
🍌三、设置组件作用域
@scope
相当于在配置文件中bean 中设置scope的作用域
@Configuration
@ComponentScan(value = {"com.wyxz.spring"},
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = {Controller.class, Service.class})})
public class MyConfig {
@Bean
// prototype 每次获取的时候才会调用
// singleton 每次获取直接从容器中拿
@Scope(value = "prototype")
public Person person() {
return new Person("张三", 23);
}
}
🍉四、懒加载
@Lazy
:让容器启动的时候先创建对象并初始化,懒加载只针对于单实例
@Configuration
@ComponentScan(value = {"com.wyxz.spring"},
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = {Controller.class, Service.class})})
public class MyConfig {
@Bean
// prototype 每次获取的时候才会调用
// singleton 每次获取直接从容器中拿
@Scope(value = "sinleton")
@Lazy
public Person person() {
return new Person("张三", 23);
}
}
🍓五、按照条件注册
@Conditional
@Configuration
@ComponentScan(value = {"com.wyxz.spring"},
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = {Controller.class, Service.class})})
public class MyConfig {
/**
* 当在Windows系统的使用加载bill,在linyx上加载linus
* @return
*/
@Conditional({WindowsCondition.class})
@Bean("bill")
public Person bill(){
return new Person("bill gates",60);
}
@Conditional({LinuxCondition.class})
@Bean("linus")
public Person linus(){
return new Person("linus", 48);
}
}
自定义条件
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;
}
}
public class LinuxCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypemetadata metadata) {
Environment environment = context.getEnvironment();
String osName = environment.getProperty("os.name");
if(osName.contains("lin")){
return true;
}
return false;
}
}
🍇六、给容器中导入组件
@import
publi class Color{}
@Import(value = {Color.class}) // 给容器中导入组件
@Configuration
public class MyConfig {
}
ImportSelector
需要实现这个接口,实现其中的方法
publi class MyImport implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.wyxz.spring.Blue"};;
}
}
@Import(value = {Color.class, MyImport.class}) // 给容器中导入组件
@Configuration
public class MyConfig {
}
registerBeanDefinitions
: 实现这个接口
public class MyImportDefinition implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean beanDefinition = registry.containsBeanDefinition("com.wyxz.spring.Color");
if (beanDefinition){
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Blue.class);
registry.registerBeanDefinition("blue",rootBeanDefinition);
}
}
}
@Import({Color.class, MyImport.class, MyImportDefinition.class})
@Configuration
public class MyConfig {}
🍑七、使用工厂bean
FactoryBean
实现这个接口,并实现其中方法
public class ColorFactory implements FactoryBean<Color> {
public Color getObject() throws Exception {
return new Color();
}
public Class<?> getObjectType() {
return Color.class;
}
}
在配置类中注册
@Configuration
public class MyConfig {
@Bean
public ColorFactory colorFactory(){
return new ColorFactory();
}
}
如果想要获取到工厂bean,可以在获得factorybean的实例前加一个"&"
😊二、组件生命周期
实现InitializingBean接口实现初始化
实现DisposableBean接口实现销毁方法
public class Car implements InitializingBean, DisposableBean {
public void afterPropertiesSet() throws Exception {
}
public void destroy() throws Exception {
}
}
@PostConstruct
:在bean创建完成并属性赋值完成之后执行
@PreDestroy
: 在容器销毁bean之前执行
🍅一、后置处理器
BeanPostProcessor
😒三、属性赋值
🥒一、使用value为属性赋值
@Value
注解设置在属性上边可以为属性赋值,当spring在加载容器的时候能获取到值
public class User {
@Value("张三")
private String name;
@Value("#{30-9}")
private Integer age;
// 获取到外部配置文件的值并为属性赋值
@Value("${email}")
private String email;
}
email=123@163.com
在配置类上添加注解
@Configuration
// 读取到外部配置文件,相当于xml配置文件中<context:property-placeholder location="classpath:user.properties" />
@PropertySource(value = {"classpath:user.properties"})
public class MyConfig{}
🍆二、自动注入
@Autowired
:按照类型查找容器组件,找到之后赋值
@Qualifier
: 指定要装配的组件的id(组合注解,和@Autowired
搭配)
@Primary
:在进行自动装配中使用默认首选的(组合注解,和@Autowried
搭配)
@Resource
: 相当于@Autowired
的注入方式,但是@Resource
是java提供的注解,而@Autowired
是spring提供的注解,按照名称进行装配
@Inject
: 相当于@Autowired
的注入方式,需要导入jar包javax inject
🍉三、自定义组件调用底层spring组件
需要实现继承了Aware接口的接口,重写其中的方法
每一个Aware接口的接口都有相对应的processor后置处理器
public class Red implements ApplicationContextAware {
}
🍐四、
@Profile
: 动态激活某一个组件,指定组件在哪个情况下才能被注册到容器中
@Configuration
@PropertySource("classpath:jdbc.properties")
public class MyConfig {
@Value("${username}")
private String username;
@Value("${password}")
private String password;
// 开发
@Bean("devDataSource")
@Profile("dev")
public DataSource dataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(username);
dataSource.setPassword(password);
dataSource.setUrl("");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
return dataSource();
}
// 测试
@Bean("testDataSource")
@Profile("test")
public DataSource dataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(username);
dataSource.setPassword(password);
dataSource.setUrl("");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
return dataSource();
}
// 生产
@Bean("productDataSource")
@Profile("product")
public DataSource dataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(username);
dataSource.setPassword(password);
dataSource.setUrl("");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
return dataSource();
}
}
激活某一个环境
- 在命令行设置启动参数:
vm options
中-Dspring.profiles.active
=要使用的环境
- 在类中设置启动环境
public class Test {
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("test","dev");
// 注册主配置类
applicationContext.register(MyConfig.class);
// 启动刷新容器
applicationContext.refresh();
}
}
😉四、面向切面编程
@Before
: 在想要执行的方法执行之前执行该方法
@After
: 在想要执行的方法执行之后执行的方法
@AfterReturning
: 在想要执行的方法执行正常返回之后执行的方法
@AfterThrowing
: 当要执行的方法抛出异常后执行该方法
@Around
: 当要执行的方法执行前后都执行该方法
public class AspectLog {
@Before()
public void before(){}
@After()
public void after(){}
@AfterReturning()
public void afterReturn(){}
@AfterThrowing()
public void afterThrow(){}
@Around()
public void around(){}
}
public class Calculator {
public int add(int a, int b){
return a + b;
}
}
将所有执行的类注册到配置类中
再配置类中添加注解
再配置类中开启切面功能@EnableAspectJAutoProxy
@Configuration
@EnableAspectJAutoProxy // 开启可用切面代理
@Aspect // 声明这是一个切面类
public class MyConfig {
@Bean
public Calculator calculator(){
return new Calculator();
}
@Bean
public AspectLog aspectLog(){
return new AspectLog();
}
}
在测试类中使用
public class Test {
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
Calculator calculator = applicationContext.getBean(Calculator.class);
calculator.add(1, 1);
}
}
一个切面类
public class MyConfig {
@Bean
public Calculator calculator(){
return new Calculator();
}
@Bean
public AspectLog aspectLog(){
return new AspectLog();
}
}
在测试类中使用
```java
public class Test {
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
Calculator calculator = applicationContext.getBean(Calculator.class);
calculator.add(1, 1);
}
}