Строительство окружающей среды
Способ аннотирования заключается во внедрении компонентов путем настройки классов. Внедрение аннотаций проще, чем внедрение XML. Внедрение аннотаций также требует добавления пакета spring-context на основе первого, что также является широко используемым методом в реальной разработке.
Подготовьте необходимые пакеты Jar
Регистрация аннотированных компонентов Spring
Spring предоставляет множество конфигураций аннотаций, поэтому мы можем реализовать регистрацию компонентов с помощью аннотаций.На следующем рисунке показаны аннотации, которые часто используются в Spring.
@ComponentScan и @Configurable
Оригинальный xml-способ
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- 要扫描的包 -->
<context:component-scan base-package="model"></context:component-scan>
</beans>
Использовать класс конфигурации@Configurable помечает класс как класс конфигурации в Spring, а @ComponentScan("model") указывает параметры, которые должны быть просканированы для класса конфигурации.
package config;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
import model.Product;
/**
* @Configurable: 该注解是标注该类是配置类
* @ComponentScan:配置要扫描的包
* @author GaoYang
*/
@Configurable
@ComponentScan("model")
public class MainConfig {
}
@Component
Используя эту аннотацию, вы можете зарегистрировать объект Java @Component в Ioc-контейнере.Если аннотация @Component присваивает свойство, оно должно быть присвоено свойству с аннотацией @Value.
/**
@Componnt可以指定该对象的id,也可以不用指定
默认id为该类的类名首字母小写
*/
@Component("students")
public class Student {
@Value("01")
private int sid;
@Value("侯宁宁")
private String name;
@Value("男")
private String sex;
класс конфигурации
/**
* @Configurable: 该注解是标注该类是配置类
* @ComponentScan:配置要扫描的包
* @author GaoYang
*/
@Configurable
@ComponentScan("model")
public class MainConfig {
}
Внедрение с использованием @Configuration
@Component("students")
public class Student {
@Value("01")
private int sid;
@Value("侯宁宁")
private String name;
@Value("男")
private String sex;
public Student() {
super();
}
public Student(int sid, String name, String sex) {
super();
this.sid = sid;
this.name = name;
this.sex = sex;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", name=" + name + ", sex=" + sex + "]";
}
}
контрольная работа
@Bean
Используя аннотацию @Bean, мы можем аннотировать метод создания объекта в нашем классе регистрации spring.Мы можем создать объект через метод, который возвращает значение объекта, и присвоить значения свойствам объекта через метод конструктор.
// 配置类
@Configurable
@ComponentScan("model")
public class MainConfig {
// 默认id为方法名
@Bean
public Product product1() {
return new Product("张三","hashd",1);
}
// 可以指定id
@Bean("product2")
public Product product2() {
return new Product("张三","hashd",1);
}
}
Объект Java-Bean
public class Product {
private String name;
private String price;
private int num;
public Product() {
super();
}
public Product(String name, String price, int num) {
super();
this.name = name;
this.price = price;
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public String toString() {
return "Product [name=" + name + ", price=" + price + ", num=" + num + "]";
}
}
контрольная работа
@TypeFilter
Аннотация @TypeFilter Это фильтровать некоторые ресурсы, задавая условия, мы можем фильтровать некоторые ресурсы и предотвращать их загрузку в контейнер ioc. Его использование должно использоваться в аннотации @ComponentScan. Значение передается через параметр excludeFilters. excludeFilters — это массив, и может быть установлено несколько @TypeFilters.
Синтаксис @TypeFilter
@Configurable
@ComponentScan(value = "model",excludeFilters = {
// FilterType.ANNOTATION是通过注解的形式进行过滤
@Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),
// FilterType.ASSIGNABLE_TYPE 是通过给定的类型
@Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {Product.class}),
// FilterType.ASPECTJ 根据正则表达式
@Filter(type = FilterType.ASPECTJ,classes = {""}),
// FilterType.CUSTOM 使用自定义规则
@Filter(type = FilterType.CUSTOM,classes = {TypeFilterImp.class})
})
public class MainConfig {
// @Bean == <bean></bean>
}
Пользовательские правила @FilterType.CUSTOM
Чтобы использовать пользовательские правила, мы должны создать для него класс создания правил. Этот класс должен реализовать интерфейс TypeFilter и метод match. Фильтр будет загружаться в соответствии с возвращаемым значением метода match. Если условие выполнено, если оно ложно, оно не будет загружено!
/**
* MetadataReader: 读取到的当前正在扫描的信息
* MetadataReaderFactory:可以获取到其他任何类的信息
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// 获取当前类注解的信息
AnnotationMetadata mr = metadataReader.getAnnotationMetadata();
// 获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取当前类的资源信息
Resource resource = metadataReader.getResource();
// 获取当前类的名字
String className = classMetadata.getClassName();
System.out.println("----"+className);
// contains包含“er”
if(className.contains("er")) {
return true;
}
return false;
}
}
@Scope
Объект, созданный Spring, по умолчанию является синглтоном, который описывается @Scope, то есть scope=«singleton».Кроме того, область действия также имеет область действия прототипа, запроса, сеанса и глобального сеанса.
Роль каждой сферы
- Шаблон singleton singleton имеет один и только один экземпляр в глобальном масштабе. (по умолчанию)
- Режим прототипа прототипа, каждый раз, когда вы получаете боб, будет новый экземпляр.
- request указывает, что новый bean-компонент будет создан для каждого HTTP-запроса, и bean-компонент действителен только в рамках текущего HTTP-запроса, настройте экземпляр: Когда используются запрос, сеанс и глобальный сеанс, в файле web.xml, который инициализирует сеть, необходимо выполнить следующую конфигурацию: Если вы используете веб-контейнер Servlet 2.4 и выше, вам нужно всего лишь добавить следующий ContextListener в файл объявления XML web.xml веб-приложения:
<web-app> ... <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> ... </web-app>
- Область сеанса означает, что для каждого HTTP-запроса будет создаваться новый компонент, и этот компонент действителен только в текущем HTTP-сеансе.
- глобальная область сеанса похожа на стандартную область сеанса HTTP, но имеет смысл только в веб-приложении с портлетом. Спецификация портлета определяет концепцию глобального сеанса, который состоит из всех различных портлетов, совместно используемых веб-приложением с портлетами. В области, определенной глобальным компонентом сеанса, определяется область действия жизненного цикла глобального сеанса портлета. Если вы используете глобальную область сеанса в сети для идентификации компонента, сеть будет автоматически использоваться как тип сеанса.
Презентация кейса
singleton
@Configurable
@ComponentScan("model")
public class MainConfig {
/**
* @Scope
* prototype: 多实例的 @Scope("prototype")
* singleton: 单实例的 @Scope("person")
* request: 一次请求创建一个实例
* session: 同一个session创建一个实例
* @return
*/
@Scope("singleton")
@Bean
public Product product() {
System.out.println("该实例已被创建");
return new Product("张三","hashd",1);
}
}
тестовый код
public class text {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("Ioc容器已创建完成!");
Product bean1 = applicationContext.getBean(Product.class);
Product bean2 = applicationContext.getBean(Product.class);
System.out.println(bean1== bean2);
}
}
Как видно из рисунка ниже, bean1 == bean2
Layz-bean
Загрузка @Layz Lai в основном предназначена для одноэлементного режима. Когда контейнер ioc инициализируется в одноэлементном режиме, объект bean-компонента вводится в контейнер. Аннотация @Layz может заставить контейнер не регистрировать контейнер при его создании, а ждать, пока первый объект bean будет зарегистрирован только тогда, когда он вызывается в следующий раз. На данный момент созданный объект все еще является одноэлементным шаблоном!
использовать синтаксис
// 配置类
@Configurable
@ComponentScan("model")
public class MainConfig {
/**
* 懒加载:
* 针对的是单实例的bean,默认在容器启动的时候创建对象
* 赖加载:容器启动时不创建对象,当第一次被调用时被创建
*
*/
@Lazy
@Bean
public Product product() {
System.out.println("该实例已被创建");
return new Product("张三","hashd",1);
}
контрольная работа
@Conditional
Аннотация @Conditional регистрируется по заданным условиям.Мне нужно создать класс конфигурации для условий конфигурации.При выполнении условий будет выполнена регистрация, а при невыполнении условий регистрация не будет выполнена .
грамматика
класс конфигурации
@Configurable
public class MainConfig {
@Conditional({winCondition.class})
@Bean("wind")
public Product wind() {
System.out.println("该实例已被创建");
return new Product("张三","wind",1);
}
Класс условия должен реализовать интерфейс Condition и добавить его как реализованный метод!
public class winCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata arg1) {
Environment environment = context.getEnvironment();
// 获取当前操作系统的名字
String property = environment.getProperty("os.name");
if(property.contains("Windows")) {
return true;
}
return false;
}
}
кейс
Требуется зарегистрировать компоненты в соответствии с текущей операционной системой.
// 配置类
@Configurable
@Import(Hero.class)
public class MainConfig {
// Windows系统
@Conditional({winCondition.class})
@Bean("wind")
public Product wind() {
System.out.println("该实例已被创建");
return new Product("张三","wind",1);
}
// Linux系统
@Conditional({linuxCondition.class})
@Bean("linux")
public Product linux() {
return new Product("李四","linux",2);
}
}
Класс конфигурации условия
public class winCondition implements Condition{
// Windows系统,返回true
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata arg1) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.contains("Windows")) {
return true;
}
return false;
}
}
public class linuxCondition implements Condition{
/**
* ConditionContext: 判断条件能使用上下文环境
* AnnotatedTypeMetadata: 注释信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 是否Linux系统
// 1、能获取到ioc使用的bean工厂
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 2、获取类加载器
ClassLoader clLoader = context.getClassLoader();
// 3、获取当前环境信息
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
// 5、bean注册类
BeanDefinitionRegistry registry = context.getRegistry();
if(property.contains("Linux")) {
return true;
}
return false;
}
контрольная работа…
@import
- @Import можно использовать только для классов. @Import добавляет экземпляры в контейнер Spring IOC посредством быстрого импорта.
- IOC присоединиться к сосуду много способов Import Notes. Относительно очень кожаная, @ импортная аннотация может использоваться для импорта сторонних пакетов, конечно же, конечно, аннотация @Bean может быть, но как можно быстро импортировать @import
- Есть три варианта использования аннотации @Import.
Первое использование: заполните массив классов напрямую
Заполните соответствующий массив классов напрямую, массив классов может иметь 0 или более. Соответствующие импортированные bean-компоненты будут добавлены в контейнер Spring, а имя bean-компонента в контейнере — это полное имя класса класса, например com.yc.
@Import({ 类名.class , 类名.class... })
public class TestDemo {
}
Второе использование: метод ImportSelector [Ключевые моменты]
Предпосылка этого метода заключается в том, что класс должен реализовать интерфейс ImportSelector.Если я хочу использовать этот метод, целевым объектом является класс Myclass.Анализ выглядит следующим образом: Создайте класс Myclass и реализуйте интерфейс ImportSelector
public class Myclass implements ImportSelector {
//既然是接口肯定要实现这个接口的方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[0];
}
}
// 分析实现接口的selectImports方法中的:
// 1、返回值: 就是我们实际上要导入到容器中的组件全类名【重点 】
// 2、参数: AnnotationMetadata表示当前被@Import注解给标注的所有注解信息【不是重点】
// 需要注意的是selectImports方法可以返回空数组但是不能返回null,否则会报空指针异常!
После приведенного выше анализа конкретные этапы использования следующие: Шаг 1: Создайте класс MyClass и реализуйте интерфейс ImportSelector, чтобы добавить полное имя класса в возвращаемое значение.
public class Myclass implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.yc.Test.TestDemo3"};
}
}
Шаг 2: Напишите класс TestDemo и пометили классы MyClass, используя режим импорта.
@Import({TestDemo2.class,Myclass.class})
public class TestDemo {
@Bean
public AccountDao2 accountDao2(){
return new AccountDao2();
}
}
Шаг 3: Напишите тестовый класс компонента в контейнере печати
**
* 打印容器中的组件测试
*/
public class AnnotationTestDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(TestDemo.class); //这里的参数代表要做操作的类
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String name : beanDefinitionNames){
System.out.println(name);
}
}
}
Третье использование: метод ImportBeanDefinitionRegistrar
Это также интерфейс, аналогичный второму использованию ImportSelector, с подобием 80%, но это использование более настраиваемое, как показано ниже:
public class Myclass2 implements ImportBeanDefinitionRegistrar {
//该实现方法默认为空
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
}
}
// 参数分析:
// 第一个参数:annotationMetadata 和之前的ImportSelector参数一样都是表示当前被@Import注解给标注的所有注解信息
// 第二个参数表示用于注册定义一个bean
Шаг 2: Напишите код для настройки зарегистрированных bean-компонентов
public class Myclass2 implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
//指定bean定义信息(包括bean的类型、作用域...)
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestDemo4.class);
//注册一个bean指定bean名字(id)
beanDefinitionRegistry.registerBeanDefinition("TestDemo4444",rootBeanDefinition);
}
}
Шаг 3: Напишите класс TestDemo и пометьте класс Myclass2 с помощью метода ImportBeanDefinitionRegistrar.
@Import({TestDemo2.class,Myclass.class,Myclass2.class})
public class TestDemo {
@Bean
public AccountDao2 accountDao222(){
return new AccountDao2();
}
}
@FactoryBean
Напишите класс конфигурации
// 标记这是一个Spring配置类
@Configuration
public class SpringConfiguration {
// 如果没有@Bean注解,则注入到容器中的id就是方法名(也就是myFactoryBean),但是如果显示的给了值,那么注入到容器中的就是factoryBean
@Bean("factoryBean")
public MyFactoryBean myFactoryBean(){
return new MyFactoryBean();
}
}
тестовый класс
public class SpringDemo {
@Test
public void springTest01() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
// 容器中获取的Bean,实际上就是工厂Bean(MyFactoryBean通过getObject()方法返回的对象)
Object factoryBean01 = context.getBean("factoryBean");
System.out.println("实际上注入到容器中的类型是:" + factoryBean01.getClass());
Object factoryBean02 = context.getBean("factoryBean");
System.out.println("注入到容器内的对象是否是单例:" + (factoryBean01 == factoryBean02));
Object factoryBean03 = context.getBean("&factoryBean");
System.out.println("如果想获取到MyFactoryBean的对象,使用&前缀:" + factoryBean03);
// 输出打印Spring中的所有Bean名称
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
Наконец
Спасибо, что прочитали это. Пожалуйста, исправьте меня, если в статье есть какие-либо недостатки. Если вы считаете, что статья полезна для вас, не забудьте поставить мне лайк. Я буду делиться техническими статьями или отраслевой информацией о Java каждый день. Добро пожаловать Всем подписаться и переслать статью!