国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

2.走向自動(dòng)裝配

rose / 789人閱讀

摘要:走向自動(dòng)裝配模式注解裝配走向自動(dòng)裝配課程介紹手動(dòng)裝配自動(dòng)裝配自動(dòng)裝配是以手動(dòng)裝配為基礎(chǔ)實(shí)現(xiàn)的手動(dòng)裝配模式注解模式注解是一種用于聲明在應(yīng)用中扮演組件角色的注解。

2.走向自動(dòng)裝配 Spring 模式注解裝配 2-1 走向自動(dòng)裝配

課程介紹

spring framework手動(dòng)裝配

spring boot自動(dòng)裝配

spring boot自動(dòng)裝配是以spring framework手動(dòng)裝配為基礎(chǔ)實(shí)現(xiàn)的

2-2 Spring Framework 手動(dòng)裝配 [模式注解(Stereotype Annotations)]()
A *stereotype annotation is an annotation that is used to declare the role that a component plays within the application. For example, the @Repository annotation in the Spring Framework is a marker for any class that fulfills the role or stereotype* of a repository (also known as Data Access Object or DAO).

@Component is a generic stereotype for any Spring-managed component. Any component annotated with @Component is a candidate for component scanning. Similarly, any component annotated with an annotation that is itself meta-annotated with @Component is also a candidate for component scanning. For example, @Service is meta-annotated with @Component.

模式注解是一種用于聲明在應(yīng)用中扮演“組件”角色的注解。如 Spring Framework 中的 @Repository 標(biāo)注在任何類上 ,用于扮演倉(cāng)儲(chǔ)角色的模式注解。

@Component 作為一種由 Spring 容器托管的通用模式組件,任何被 @Component 標(biāo)注的組件均為組件掃描的候選對(duì)象。類似地,凡是被 @Component 元標(biāo)注(meta-annotated)的注解,也即被@Component 注解標(biāo)注過的注解,如 @Service ,且這兩個(gè)注解的簽名也一致時(shí),當(dāng)任何組件標(biāo)注它時(shí),也被視作組件掃描的候選對(duì)象 。

模式注解舉例
Spring Framework 注解 場(chǎng)景說明 起始版本
@Repository 數(shù)據(jù)倉(cāng)儲(chǔ)模式注解 2.0
@Component 通用組件模式注解 2.5
@Service 服務(wù)模式注解 2.5
@Controller Web 控制器模式注解 2.5
@Configuration 配置類模式注解 3.0
裝配方式
方式



        

        
        
@ComponentScan 方式
@ComponentScan(basePackages = "com.imooc.dive.in.spring.boot")
public class SpringConfiguration {
...
} 
2-3 Spring Framework手動(dòng)裝配自定義模式注解 自定義模式注解

@firstLevelRepository注解“繼承”了@repository,同時(shí)@repository注解又“繼承”了@component,三個(gè)注解在注解關(guān)系上層層“繼承”,同時(shí)注解的簽名字段即注解屬性方法也一致,只有一個(gè)value字段,用于指定bean的name。同理,@SecondLevelRepository注解被@FirstLevelRepository注解標(biāo)注也會(huì)有同樣的效果,體現(xiàn)了層次性。 “派生性”側(cè)重于從spring已有的注解生成新的注解,“層次性”側(cè)重于這些注解之間所謂的層層”繼承“關(guān)系。

@Component “派生性”

FirstLevelRepository注解定義

package com.imooc.springbootautoconfigure.annotation;
import org.springframework.stereotype.Repository;
import java.lang.annotation.*;
/**
 * 一級(jí) {@link Repository @Repository}
 *
 * @author gaorj
 * @since 2018/10/16
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository
public @interface FirstLevelRepository {

    String value() default "";

}
@Component “層次性”

@SecondLevelRepository注解定義

package com.imooc.springbootautoconfigure.annotation;

import java.lang.annotation.*;

/**
 * @author gaorj
 * @since 2018/10/16
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FirstLevelRepository
public @interface SecondLevelRepository {

    String value() default "";

}

兩個(gè)自定義注解的使用

package com.imooc.springbootautoconfigure.repository;

import com.imooc.springbootautoconfigure.annotation.FirstLevelRepository;
import com.imooc.springbootautoconfigure.annotation.SecondLevelRepository;
import org.springframework.stereotype.Component;

/**
 *
 * @author gaorj
 * @since 2018/10/16
 */
//@FirstLevelRepository(value = "myFirstLevelRepository")//value指定bean的名稱
//@Component(value = "myFirstLevelRepository")//同樣的效果,注解的派生性
@SecondLevelRepository(value = "myFirstLevelRepository")//同樣的效果,注解的層次性
public class MyFirstLevelRepository {
}

Repository啟動(dòng)類的使用,用于驗(yàn)證自定義注解的使用。此處沒有使用默認(rèn)的@SpringBootApplication注解,使用SpringApplicationBuilder初始化上下文

package com.imooc.springbootautoconfigure.bootstrap;

import com.imooc.springbootautoconfigure.repository.MyFirstLevelRepository;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/**
 * Repository啟動(dòng)類
 * @author gaorj
 * @since 2018/10/16
 */
//掃描bean目錄
@ComponentScan(value ="com.imooc.springbootautoconfigure.repository")
public class RepositoryBootstrap {

    public static void main(String[] args) {
        //springboot上下文初始化
        ConfigurableApplicationContext context = new SpringApplicationBuilder(RepositoryBootstrap.class)
                //非web工程
                .web(WebApplicationType.NONE)
                .run(args);
        //myFirstLevelRepository bean是否存在
        MyFirstLevelRepository myFirstLevelRepository = context.getBean("myFirstLevelRepository", MyFirstLevelRepository.class);

        System.out.println("myFirstLevelRepository"+myFirstLevelRepository);


        //關(guān)閉上下文
        context.close();
    }
}
Spring @Enable 模塊裝配

Spring Framework 3.1 開始支持”@Enable 模塊驅(qū)動(dòng)“。所謂“模塊”是指具備相同領(lǐng)域的功能組件集合, 組合所形成一個(gè)獨(dú)立的單元。所謂模塊是為了實(shí)現(xiàn)一個(gè)功能所涉及到的各個(gè)組件的集合。比如 Web MVC 模塊、AspectJ代理模塊、Caching(緩存)模塊、JMX(Java 管 理擴(kuò)展)模塊、Async(異步處理)模塊等。

2-4 @Enable 模塊裝配兩種方式 @Enable 注解模塊舉例
框架實(shí)現(xiàn) @Enable 注解模塊 激活模塊
Spring Framework @EnableWebMvc Web MVC 模塊
@EnableTransactionManagement 事務(wù)管理模塊
@EnableCaching Caching 模塊
@EnableMBeanExport JMX 模塊
@EnableAsync 異步處理模塊
EnableWebFlux Web Flux 模塊
@EnableAspectJAutoProxy AspectJ 代理模塊
Spring Boot @EnableAutoConfiguration 自動(dòng)裝配模塊
@EnableManagementContext Actuator 管理模塊
@EnableConfigurationProperties 配置屬性綁定模塊
@EnableOAuth2Sso OAuth2 單點(diǎn)登錄模塊
Spring Cloud @EnableEurekaServer Eureka服務(wù)器模塊
@EnableConfigServer 配置服務(wù)器模塊
@EnableFeignClients Feign客戶端模塊
@EnableZuulProxy 服務(wù)網(wǎng)關(guān) Zuul 模塊
@EnableCircuitBreaker 服務(wù)熔斷模塊
實(shí)現(xiàn)方式
注解驅(qū)動(dòng)方式

通過引入@Import一個(gè)被@configuration模式注解的類來實(shí)現(xiàn)此模塊的功能,加載相應(yīng)的bean。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
@Configuration
public class DelegatingWebMvcConfiguration extends
WebMvcConfigurationSupport {
...
}
接口編程方式

引入@Import的類必須實(shí)現(xiàn)ImportSelector接口,此接口能夠返回多個(gè)配置bean,根據(jù)注解配置的簽名信息決定引入bean,從而實(shí)現(xiàn)模塊裝配的多樣化。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {
...
}
public class CachingConfigurationSelector extends AdviceModeImportSelector {
/**
* {@inheritDoc}
* @return {@link ProxyCachingConfiguration} or {@code
AspectJCacheConfiguration} for
* {@code PROXY} and {@code ASPECTJ} values of {@link
EnableCaching#mode()}, respectively
*/
public String[] selectImports(AdviceMode adviceMode) {
            switch (adviceMode) {
                case PROXY:
                return new String[] {                AutoProxyRegistrar.class.getName(),ProxyCachingConfiguration.class.getName() };
                case ASPECTJ:
            return new String[] {
        AnnotationConfigUtils.CACHE_ASPECT_CONFIGURATION_CLASS_NAME };
                default:
                return null;
            }
}

ImportSelector接口

package org.springframework.context.annotation;

import org.springframework.core.type.AnnotationMetadata;

/**
 * Interface to be implemented by types that determine which @{@link Configuration}
 * class(es) should be imported based on a given selection criteria, usually one or more
 * annotation attributes.
 *
 * 

An {@link ImportSelector} may implement any of the following * {@link org.springframework.beans.factory.Aware Aware} interfaces, and their respective * methods will be called prior to {@link #selectImports}: *

    *
  • {@link org.springframework.context.EnvironmentAware EnvironmentAware}
  • *
  • {@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
  • *
  • {@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
  • *
  • {@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
  • *
* *

ImportSelectors are usually processed in the same way as regular {@code @Import} * annotations, however, it is also possible to defer selection of imports until all * {@code @Configuration} classes have been processed (see {@link DeferredImportSelector} * for details). * * @author Chris Beams * @since 3.1 * @see DeferredImportSelector * @see Import * @see ImportBeanDefinitionRegistrar * @see Configuration */ public interface ImportSelector { /** * Select and return the names of which class(es) should be imported based on * the {@link AnnotationMetadata} of the importing @{@link Configuration} class. */ String[] selectImports(AnnotationMetadata importingClassMetadata); }

自定義 @Enable 模塊
基于注解驅(qū)動(dòng)實(shí)現(xiàn) - @EnableHelloWorld

HelloWorldConfiguration -> HelloWorld

自定義@EnableHelloWorld注解

package com.imooc.springbootautoconfigure.annotation;

import com.imooc.springbootautoconfigure.configuration.HelloWorldConfiguration;
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

/**
 * @author gaorj
 * @since 2018/10/16
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
//@Import(HelloWorldConfiguration.class)//注解驅(qū)動(dòng)實(shí)現(xiàn)方式
@Import(HelloWorldImportSelector.class)//接口編程實(shí)現(xiàn)方式
public @interface EnableHelloWorld {
}

基于@Configuration注解import引入的配置類

package com.imooc.springbootautoconfigure.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author gaorj
 * @since 2018/10/16
 */
@Configuration
public class HelloWorldConfiguration {

    @Bean
    public String helloWorld() { // 方法名即 Bean 名稱
        return "Hello,World 2018";
    }
}
基于接口驅(qū)動(dòng)實(shí)現(xiàn) - @EnableServer

HelloWorldImportSelector -> HelloWorldConfiguration -> HelloWorld

基于實(shí)現(xiàn)ImportSelector接口import引入的配置類

package com.imooc.springbootautoconfigure.annotation;

import com.imooc.springbootautoconfigure.configuration.HelloWorldConfiguration;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @author gaorj
 * @since 2018/10/16
 */
public class HelloWorldImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{HelloWorldConfiguration.class.getName()};
    }
}

驗(yàn)證@EnableHelloWorld啟動(dòng)類

package com.imooc.springbootautoconfigure.bootstrap;

import com.imooc.springbootautoconfigure.annotation.EnableHelloWorld;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author gaorj
 * @since 2018/10/16
 */
@EnableHelloWorld
public class EnableHelloWorldBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableHelloWorldBootstrap.class)
                .web(WebApplicationType.NONE)
                .run(args);

        // helloWorld Bean 是否存在
        String helloWorld =
                context.getBean("helloWorld", String.class);

        System.out.println("helloWorld Bean : " + helloWorld);

        // 關(guān)閉上下文
        context.close();

    }
}

兩種實(shí)現(xiàn)方式對(duì)比,接口驅(qū)動(dòng)實(shí)現(xiàn)由于中間經(jīng)過ImportSelector轉(zhuǎn)換,此種方式相比注解驅(qū)動(dòng)實(shí)現(xiàn)更有彈性,能夠?qū)崿F(xiàn)bean加載方式的多樣化,自定義實(shí)現(xiàn)多種返回值,類似于條件裝配。

Spring 條件裝配 2-5 Spring條件裝配

從 Spring Framework 3.1 開始,允許在 Bean 裝配時(shí)增加前置條件判斷

條件注解舉例
Spring 注解 場(chǎng)景說明 起始版本
@Profile 配置化條件裝配 3.1
@Conditional 編程條件裝配 4.0

profile參數(shù)配置方式有局限,conditional自定義編程更大的靈活性

實(shí)現(xiàn)方式
配置方式 - @Profile

@profile注解實(shí)際上是通過@conditional注解實(shí)現(xiàn)的

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {

    /**
     * The set of profiles for which the annotated component should be registered.
     */
    String[] value();

}
編程方式 - @Conditional

@Conditional 注解的定義及其使用,必須配合Condition接口使用。

判斷@Conditional注解的簽名類OnClassCondition.class是否在當(dāng)前classpath下存在。

OnClassCondition.class這個(gè)類必須實(shí)現(xiàn)Condition接口,在此類中根據(jù) @ConditionalOnClass注解的簽名信息作匹配判斷,是否裝配此bean。

/**
 * {@link Conditional} that only matches when the specified classes are on the classpath.
 *
 * @author Phillip Webb
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {

    /**
     * The classes that must be present. Since this annotation is parsed by loading class
     * bytecode, it is safe to specify classes here that may ultimately not be on the
     * classpath, only if this annotation is directly on the affected component and
     * not if this annotation is used as a composed, meta-annotation. In order to
     * use this annotation as a meta-annotation, only use the {@link #name} attribute.
     * @return the classes that must be present
     */
    Class[] value() default {};

    /**
     * The classes names that must be present.
     * @return the class names that must be present.
     */
    String[] name() default {};

}

@Conditional注解的定義

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

    /**
     * All {@link Condition}s that must {@linkplain Condition#matches match}
     * in order for the component to be registered.
     */
    Class[] value();

}

Condition接口

public interface Condition {

   /**
    * Determine if the condition matches.
    * @param context the condition context
    * @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
    * or {@link org.springframework.core.type.MethodMetadata method} being checked.
    * @return {@code true} if the condition matches and the component can be registered
    * or {@code false} to veto registration.
    */
   boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}
2-6 基于配置方式實(shí)現(xiàn)自定義條件裝配 自定義條件裝配
基于配置方式實(shí)現(xiàn) - @Profile

計(jì)算服務(wù),多整數(shù)求和 :sum

@Profile("Java7") : for 循環(huán)

@Profile("Java8") : Lambda

CalculateService求和接口

package com.imooc.springbootautoconfigure.service;

/**
 * @author gaorj
 * @since 2018/10/16
 */
public interface CalculateService {

    /**
     * 從多個(gè)整數(shù) sum 求和
     * @param values 多個(gè)整數(shù)
     * @return sum 累加值
     */
    Integer sum(Integer... values);

}

CalculateService求和接口java7實(shí)現(xiàn)

package com.imooc.springbootautoconfigure.service;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

/**
 * @author gaorj
 * @since 2018/10/16
 */
@Service
@Profile("Java7")
public class Java7CalculateService implements CalculateService {
    @Override
    public Integer sum(Integer... values) {
        System.out.println("Java 7 for 循環(huán)實(shí)現(xiàn) ");
        int sum = 0;
        for (int i = 0; i < values.length; i++) {
            sum += values[i];
        }
        return sum;
    }

    public static void main(String[] args) {
        CalculateService calculateService = new Java7CalculateService();
        System.out.println(calculateService.sum(1,2,3,4,5,6,7,8,9,10));
    }
}

CalculateService求和接口java8實(shí)現(xiàn)

package com.imooc.springbootautoconfigure.service;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

import java.util.stream.Stream;

/**
 * @author gaorj
 * @since 2018/10/16
 */
@Service
@Profile("Java8")//條件配置裝配
public class Java8CalculateService implements CalculateService{
    @Override
    public Integer sum(Integer... values) {
        System.out.println("Java 8 Lambda 實(shí)現(xiàn)");
        //Integer sum = Stream.of(values).reduce(0, (integer1, integer2) -> integer1 + integer2);
        int sum = Stream.of(values).reduce(0, Integer::sum);
        return sum;
    }

    public static void main(String[] args) {
        CalculateService calculateService = new Java8CalculateService();
        System.out.println(calculateService.sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    }
}

@Profile啟動(dòng)類驗(yàn)證

package com.imooc.springbootautoconfigure.bootstrap;

import com.imooc.springbootautoconfigure.service.CalculateService;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author gaorj
 * @since 2018/10/16
 */
@SpringBootApplication(scanBasePackages ="com.imooc.springbootautoconfigure.service")
public class CalculateServiceBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(CalculateServiceBootstrap.class).web(WebApplicationType.NONE)
                .profiles("Java7")
                .run(args);

        // CalculateService Bean 是否存在
        CalculateService calculateService = context.getBean(CalculateService.class);

        System.out.println("calculateService.sum(1...10) : " +
                calculateService.sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

        // 關(guān)閉上下文
        context.close();
    }
}
2-7 基于編程方式實(shí)現(xiàn)條件裝配
基于編程方式實(shí)現(xiàn) - @ConditionalOnSystemProperty

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/71714.html

相關(guān)文章

  • Java深入-框架技巧

    摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進(jìn)階面試問題列表 -...

    chengtao1633 評(píng)論0 收藏0
  • 第二章 裝配Bean

    摘要:構(gòu)造器自動(dòng)裝配方法自動(dòng)裝配其他方法自動(dòng)裝配不管是構(gòu)造器,方法還是其他的方法,都會(huì)去嘗試滿足方法參數(shù)上所聲明的依賴。所以上面的輸出是構(gòu)造器自動(dòng)裝配方法自動(dòng)裝配其他方法自動(dòng)裝配使用進(jìn)行自動(dòng)裝配的時(shí)候,需要注意一下幾點(diǎn)。 完整代碼請(qǐng)見:https://github.com/codercuixi... 創(chuàng)建應(yīng)用對(duì)象之間協(xié)作關(guān)系的行為通常稱為裝配(wiring),這也是依賴注入(DI)的本質(zhì)。 ...

    xcold 評(píng)論0 收藏0
  • Spring - 裝配Bean

    摘要:裝配任何一個(gè)成功的應(yīng)用都是由多個(gè)為了實(shí)現(xiàn)某個(gè)業(yè)務(wù)目標(biāo)而相互協(xié)作的組件構(gòu)成的創(chuàng)建應(yīng)用對(duì)象之間協(xié)作關(guān)系的行為通常稱為裝配,這也是依賴注入配置的可選方案在中進(jìn)行顯示配置在中進(jìn)行顯示配置隱式的發(fā)現(xiàn)機(jī)制和自動(dòng)裝配自動(dòng)化裝配組件掃描會(huì)自動(dòng)發(fā)現(xiàn)應(yīng)用上下文 裝配Bean 任何一個(gè)成功的應(yīng)用都是由多個(gè)為了實(shí)現(xiàn)某個(gè)業(yè)務(wù)目標(biāo)而相互協(xié)作的組件構(gòu)成的 創(chuàng)建應(yīng)用對(duì)象之間協(xié)作關(guān)系的行為通常稱為裝配(wiring)...

    CNZPH 評(píng)論0 收藏0
  • 使用Spring annotation編程的快感

    摘要:創(chuàng)建應(yīng)用對(duì)象之間協(xié)作關(guān)系的行為通常稱為裝配中有三種裝配的方法在中顯式配置在中顯式配置隱式的發(fā)現(xiàn)機(jī)制和自動(dòng)裝配這兒要說的就是第三個(gè)自動(dòng)發(fā)現(xiàn)與裝配,它會(huì)帶來編程的快感。 一、前言 Spring的Bean Factory所實(shí)現(xiàn)的IoC輕量級(jí)容器,可以很方便地讓大家基于POJO開發(fā)JavaEE應(yīng)用程序。 創(chuàng)建應(yīng)用對(duì)象之間協(xié)作關(guān)系的行為通常稱為裝配 Spring中有三種裝配Bean的方法 在X...

    BWrong 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<