Spring常用组件注册注解开发案例
文章目录
什么是spring注解开发?
就是不再使用Spring的bean.xml文件,纯使用注解的方式开发;
要使用纯注解开发,就需要有一个配置类,配置类==配置文件
spring版本:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.5.RELEASE</version> </dependency>
1. 组件注册注解
1. @Configuration
@Configuration:一旦在某个类上标注了此注解,说明此类就是一个配置类
注解的定义如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(
annotation = Component.class
)
String value() default "";
}
2.@Bean注解
@Bean:给容器中注册一个bean;类型为返回值的类型,id默认使用方法名作为id
注解的定义如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String[] value() default {};
@AliasFor("value")
String[] name() default {};
/** @deprecated */
@Deprecated
Autowire autowire() default Autowire.NO;
boolean autowireCandidate() default true;
String initMethod() default "";
String destroyMethod() default "(inferred)";
}
3. @Configuration与@Bean注解使用案例
定义一个名为Person的类,如下
package com.yuan.bean;
public class Person {
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
-
传统的方式实现注册一个bean的方式:
1.编写spring的核心配置文件,如bean.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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!--包扫描xml配置:只要标注了@Controller、@Service、@Repository、@Component等注解,它们会自动的加载到IOC容器中--> <!--<context:component-scan base-package="com.yuan"></context:component-scan>--> <!--使用set方式赋值--> <bean id="person" class="com.yuan.bean.Person"> <property name="age" value="22" /> <property name="name" value="jinshengyuan"/> </bean> </beans>
- 加载spring核心配置文件 bean.xml文件来初始化一个Person类
package com.yuan; import com.yuan.bean.Person; import com.yuan.config.MainConfig; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainTest { public static void main(String[] args) { //xml配置的方式 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml"); Person person = (Person) applicationContext.getBean("person"); System.out.println(person); } } } 执行结果:Person{name='jinshengyuan', age=22}
-
使用注解驱动开发方式注册一个bean
- 编写一个配置类,如下面的MainConfig.java
package com.yuan.config; import com.yuan.bean.Person; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; //配置类 == 配置文件 @Configuration //告诉spring这是一个配置类 public class MainConfig { /** * @Bean注解: 给容器中注册一个bean;类型为返回值的类型,id默认使用方法名作为id * 如果要自己指定id,则需要加上name属性,如:@bean(value="person"),value可省略写成@Bean("person") * @return */ @Bean(name = "person") public Person person01(){ return new Person("张三",20); } }
- 初始化bean
package com.yuan; import com.yuan.bean.Person; import com.yuan.config.MainConfig; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainTest { public static void main(String[] args) { //xml配置的方式 /*ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml"); Person person = (Person) applicationContext.getBean("person"); System.out.println(person);*/ //使用注解的方式为IOC容器注册一个组件 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); Person person = applicationContext.getBean(Person.class); System.out.println(person); //根据类型获取bean的名称 String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class); for (int i=0;i<beanNamesForType.length;i++){ System.out.println(beanNamesForType[i]); } } }
4. ComponentScan注解
@ComponentScan:只要标注了@Controller、@Service、@Repository、@Component等注解,它们会通过@ComponentScan自动的加载到IOC容器中
@ComponentScan属性:
- value:指定自动扫描的包
- excludeFilters = ComponentScan.Filter[] : 指定扫描的时候按照什么规则排除哪些组件;
- includeFilters = ComponentScan.Filter[] : 指定扫描的时,只需要包含哪些组件,还需配合与禁用默认规则一起使用;
- useDefaultFilters = false : 禁用自动扫描的默认规则
@ComponentScan.Filter的属性:
@ComponentScan.Filter的属性type过滤规则
FilterType.ANNOTATION:按照注解(常用)
FilterType.ASSIGNABLE_TYPE :按照给定的类型(常用)
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.CUSTOM :使用自定义规则
FilterType.REGEX :使用正则表达式指定
- xml配置方法:
<context:component-scan base-package="com.yuan"></context:component-scan>
- 注解方式:Java8+
package com.yuan.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
@Configuration
@ComponentScan(value = "com.yuan",excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
},includeFilters = {
@ComponentScan.Filter(type =FilterType.ANNOTATION,classes = {Service.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes ={BookServices.class}
},useDefaultFilters = false) //自动扫描的包
//excludeFilters = ComponentScan.Filter[] : 指定扫描的时候按照什么规则排除哪些组件
//includeFilters = ComponentScan.Filter[] : 指定扫描的时,只需要包含哪些组件,还需配合禁用掉默认规则一起使用
//useDefaultFilters = false : 禁用自动扫描的的默认规则
//如果是Java8版本,则可以多次使用@ComponentScan注解,如果Java8之前的版本,则使用@ComponentScans注解来多次使用@ComponentScan注解
@ComponentScan(...) //java8中可以写多个@ComponentScan
@ComponentScan(...) //java8中可以写多个@ComponentScan
public class MyConfigOne {
@Bean("person")
public Person person(){
return new Person("李四",25);
}
}
- 注解方式:Java8以下版本要配置多个@ComponentScan时使用@ComponentScans注解来做
package com.yuan.config;
import com.yuan.bean.Person;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
@Configuration
@ComponentScans(
value = {
@ComponentScan(value = "com.yuan", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
}, includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Service.class})
}, useDefaultFilters = false) //自动扫描的包
}
)
//excludeFilters = ComponentScan.Filter[] : 指定扫描的时候按照什么规则排除哪些组件
//includeFilters = ComponentScan.Filter[] : 指定扫描的时,只需要包含哪些组件,还需配合禁用掉默认规则一起使用
//useDefaultFilters = false : 禁用自动扫描的的默认规则
//如果是Java8版本,则可以多次使用@ComponentScan注解,如果Java8之前的版本,则使用@ComponentScans注解来多次使用@ComponentScan注解
public class MyConfigOne {
@Bean("person")
public Person person(){
return new Person("李四",25);
}
}
5. 自定义TypeFilter指定过滤规则
- 编写自定义规则类
package com.yuan.config;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import java.io.IOException;
/**
* @ComponentScan.Filter 的type属性自定义规则类(type = FilterType.CUSTOM),实现了TypeFilter接口
*/
public class MyTypeFilter implements TypeFilter {
/**
*
* @param metadataReader the metadata reader for the target class (读取到的正在扫描的类的信息)
* @param metadataReaderFactory a factory for obtaining metadata readers (是一个工厂,可以获取其他任何类的信息)
* * for other classes (such as superclasses and interfaces)
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的信息,比它的类型式什么,实现了哪些接口等等
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类的类名
String className = classMetadata.getClassName();
System.out.println("---className---->>>>"+className);
//获取当前类的资源信息(如类的路径)
Resource resource = metadataReader.getResource();
//如果类名中包含er则匹配成功
if(className.contains("er")){
return true;
}
return false;
}
}
- 自定义规则配置类
package com.yuan.config;
import com.yuan.bean.Person;
import org.springframework.context.annotation.*;
@Configuration
//如果Java8之前的版本,则使用@ComponentScans注解来多次使用@ComponentScan注解
@ComponentScans(
value = {
@ComponentScan(value = "com.yuan", includeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
}, useDefaultFilters = false) //自动扫描的包
}
)
/*
@ComponentScan.Filter过滤规则
FilterType.ANNOTATION:按照注解(常用)
FilterType.ASSIGNABLE_TYPE :按照给定的类型(常用)
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.CUSTOM :使用自定义规则
FilterType.REGEX :使用正则表达式指定
*/
public class MyConfigTwo {
@Bean(value = "person")
public Person person() {
return new Person("张三", 33);
}
}
- 测试
package com.yuan.test;
import com.yuan.config.MainConfig;
import com.yuan.config.MyConfigTwo;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class IOCTest {
@Test
public void testTwo(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigTwo.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
- 执行结果:
---className---->>>>com.yuan.test.IOCTest
---className---->>>>com.yuan.MainTest
---className---->>>>com.yuan.bean.Person
---className---->>>>com.yuan.config.MainConfig
---className---->>>>com.yuan.config.MyConfigOne
---className---->>>>com.yuan.config.MyTypeFilter
---className---->>>>com.yuan.controller.BookController
---className---->>>>com.yuan.dao.BookDao
---className---->>>>com.yuan.services.BookServices
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfigTwo ----配置类自己
person ----@Bean加载的person类,由容器创建的,所有会看到
下面这三个就是由MyTypeFilter过滤规则进行过滤的类
myTypeFilter
bookController
bookServices