spring-ioc基礎(chǔ)學(xué)習(xí)(3)基于JavaConfig的配置實現(xiàn),脫離xml配置

使用JavaConfig配置,替代原本spring的xml配置

主要目標(biāo)

    1. 學(xué)習(xí)JavaConfig替代spring的xml配置
    1. 熟悉相關(guān)的注解配置

JavaConfig的引入

spring從3.0版本引入JavaConfig提供配置功能,就可以使用JavaConfig替代xml文件進行配置,從4.0開始支持springboot后,springboot完全采用JavaConfig的方式進行開發(fā)配置

JavaConfig的使用

1)構(gòu)建spring項目

    1. 建立maven項目
    1. pom.xml文件中引入所需jar包
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.21</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>
    1. 建立JavaConfig配置類,使用@Configuration進行標(biāo)注后被java自動識別為JavaConfig類
@Configuration
public class IocJavaConfig {}
  • 4.建立測試使用的接口和類
com.learn.controller
UserController
com.learn.service
IBeanService
com.learn.service.impl
UserServiceImpl
com.learn.dao
IBeanDao
com.learn.dao.impl
UserDaoImpl
com.learn.bean
User
Role
    1. 建立外部配置文件
mysql.username=mall
mysql.password=mall
mysql.url=jdbc:mysql://192.168.1.150:3306/mall
mysql.driver=com.mysql.jdbc.Driver

2)進行類的裝載配置

  • 1.裝載外部類,使用@Bean注解進行裝載注冊
    /**
     *@Bean 將一個類的實例,注冊到容器中成為一個容器中的bean被調(diào)用
     * @return
     */
    @Bean
    public DruidDataSource druidDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setName(Db.NAME);
        dataSource.setPassword(Db.PASSWORD);
        dataSource.setUrl(Db.URL);
        dataSource.setDriverClassName(Db.DRIVER);
        System.out.println("注冊DruidDataSource");
        return dataSource;
    }

測試

    /**
     * 測試通過@Bean進行第三方類注入
     */
    @Test
    public void test01(){
        DruidDataSource druidDataSource = context.getBean("druidDataSource",DruidDataSource.class);
        DruidDataSource druidDataSource1 = context.getBean(DruidDataSource.class);
        DruidDataSource druidDataSource2 = (DruidDataSource)context.getBean("druidDataSource");
        System.out.println(druidDataSource);
    }
  • 2.裝載配置屬性文件,使用@PropertySource標(biāo)簽將屬性文件裝載,并使用${}方式讀取屬性文件
@Configuration
@PropertySource("classpath:db.properties")
public class IocJavaConfig{
    private static class Db{
        @Value("${mysql.name}")
        private static String NAME;
        @Value("${mysql.password}")
        private static String PASSWORD;
        @Value("${mysql.url}")
        private static String URL;
        @Value("${mysql.driver}")
        private static String DRIVER;
    }
}
  • 3.包掃描方式添加注冊類,@ComponentScan標(biāo)簽指定對應(yīng)的包路徑,會將包內(nèi)標(biāo)注了@Component組件標(biāo)簽的類裝載到容器中
@Configuration
@ComponentScan({"com.learn.dao","com.learn.service","com.learn.controller"},
includeFilters={@ComponentScan.Filter(type=FilterType.ANNOTATION,value = {Controller.class, Service.class})},useDefaultFilters = false
)
@PropertySource("classpath:db.properties")
public class IocJavaConfig{}
@Service("userService")
public class UserServiceImpl implements IBeanService<User> {
    public UserServiceImpl() {
        System.out.println("創(chuàng)建UserServiceImpl");
    }

    @Autowired
    IBeanDao<User> userDao;

    @Override
    public User insert(User user) {
        return userDao.insert(user);
    }

    @Override
    public boolean delete(Long id) {
        return userDao.delete(id);
    }

    @Override
    public User update(Long id, User user) {
        return userDao.update(id, user);
    }

    @Override
    public List<User> listAll() {
        return userDao.listAll();
    }
}

測試

    /**
     *測試通過@ComponentScan進行包掃描
     */
    @Test
    public void test02(){
        IBeanService<User> userService = context.getBean(IBeanService.class);
        userService.listAll();
        userService = context.getBean("userService",IBeanService.class);
        userService.listAll();
    }
  • 4.注冊內(nèi)部類
    /**
     * 內(nèi)部bean的相互調(diào)用直接使用方法
     * @Bean可以設(shè)置多個name別名用來進行獲取bean實例
     * @return
     */
    @Bean(name={"userwx","wx"})
    public User user(){
        User user = new User();
        user.setId(1L);
        user.setName("wx");
        user.setWife(wife());
        return user;
    }
    @Bean
    public Wife wife(){
        Wife wife = new Wife();
        wife.setId(2L);
        wife.setName("bxl");
        return wife;
    }

測試

    /**
     * 測試內(nèi)部bean的相互調(diào)用直接使用方法
     */
    @Test
    public void test03(){
        User user = context.getBean("userwx",User.class);
        User user2 = context.getBean(User.class);
        System.out.println(user);
    }
  • 5.在@Bean中設(shè)置生命周期函數(shù)@Bean(initMethod = "methodName",destroyMethod = "methodName")
public class Wife extends Person{
    public Wife() {
        System.out.println("創(chuàng)建wife");
    }
    public void init(){
        System.out.println("初始化wife");
    }
    public void destroy(){
        System.out.println("注銷wife");
    }
}
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Wife wife(){
        Wife wife = new Wife();
        wife.setId(2L);
        wife.setName("bxl");
        return wife;
    }

測試

    /**
     * 測試@Bean的生命周期
     */
    @Test
    public void test03(){
        User user = context.getBean("userwx",User.class);
        User user2 = context.getBean(User.class);
        System.out.println(user);
    }
    1. 指定bean的作用域@Scope標(biāo)簽
    1. 導(dǎo)入其他配置類或其他類使用@Import

就像在Spring XML文件中使用<import/>元素來幫助模塊化配置一樣;
@Import 注解允許從另一個配置類加載@Bean定義

@Configuration
@ComponentScan({"com.learn.dao","com.learn.service","com.learn.controller"})
@PropertySource("classpath:db.properties")
@Import(value = {AuxiliaryConfig.class, Role.class})
public class IocJavaConfig{}
@Configuration
public class AuxiliaryConfig {
    @Bean(name = {"person","p"})
    public Person person(){
        Person person = new Person();
        person.setId(3L);
        person.setName("person");
        return person;
    }
}
public class Person {
    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
public class Role {
    public Role() {
        System.out.println("實例化Role");
    }

    @Value("1")
    private long id;
    @Value("admin")
    private String roleName;

    @Override
    public String toString() {
        return new StringJoiner(", ", Role.class.getSimpleName() + "[", "]")
                .add("id=" + id)
                .add("roleName='" + roleName + "'")
                .toString();
    }
}

測試

    /**
     * 測試通過@Import進行類注入
     */
    @Test
    public void test04(){
        Role role = context.getBean(Role.class);
        System.out.println(role);
        Person person = context.getBean("p",Person.class);
        System.out.println(person);
    }

注解解析

@Configuration

使用方式

使用在類、接口(包括注釋類型)或枚舉聲明之上

作用

用作標(biāo)識配置類,替換spring的xml配置文件,作用等價于<beans>標(biāo)簽,在其中可以進行的操作:

  1. 聲明要注冊的類 @Bean
  2. 導(dǎo)入其他配置文件 @Import
  3. 進行包掃描@ComponentScan等操作

源碼

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(annotation = Component.class)
    String value() default "";
    boolean proxyBeanMethods() default true;
}

@Bean

使用方式

使用在方法,聲明類型上

作用

指示一個方法生成一個由Spring容器管理的bean,等價于spring的xml配置文件中的<bean>標(biāo)簽,用來將一個實例對象注入到容器中,可以進行的操作有:

  1. 設(shè)定類的生命周期 initMethod,destroyMethod
  2. 設(shè)置別名 name

源碼

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented

public @interface Bean {

    @AliasFor("name")
    String[] value() default {};

    @AliasFor("value")
    String[] name() default {};

    @Deprecated
    Autowire autowire() default Autowire.NO;

    boolean autowireCandidate() default true;

    String initMethod() default "";

    String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;

}

@Import

使用方式

使用在類、接口(包括注釋類型)或枚舉聲明之上

作用

引入指定的類,可以引入多個,以及可以引入第三方包,用于將相關(guān)的類直接注冊到容器中

源碼

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    Class<?>[] value();
}

@ComponentScan

使用方式

使用在類、接口(包括注釋類型)或枚舉聲明之上

作用

掃描定義的包路徑,將包路徑中進行使用@Component相關(guān)注解標(biāo)注的文件,注冊到容器中,可以設(shè)定掃描包中的加載方式是否為懶加載,設(shè)置過濾,掃描或不掃描某些類,配置

源碼

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {

    
    @AliasFor("basePackages")
    String[] value() default {};

    
    @AliasFor("value")
    String[] basePackages() default {};

    
    Class<?>[] basePackageClasses() default {};

    
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;


    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    
    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    
    String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;

    
    boolean useDefaultFilters() default true;

    
    Filter[] includeFilters() default {};

    Filter[] excludeFilters() default {};

    boolean lazyInit() default false;


    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    @interface Filter {

        
        FilterType type() default FilterType.ANNOTATION;

        
        @AliasFor("classes")
        Class<?>[] value() default {};
        
        @AliasFor("value")
        Class<?>[] classes() default {};
        
        String[] pattern() default {};

    }

}

@PropertySource

使用方式

使用在類、接口(包括注釋類型)或枚舉聲明之上

作用

導(dǎo)入外部的配置文件

源碼

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {

    String name() default "";

    String[] value();

    
    boolean ignoreResourceNotFound() default false;

    String encoding() default "";

    Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}

@Autowired

使用方式

使用在構(gòu)造器,方法,形參,字段聲明(包括枚舉常量),注釋聲明之上

作用

自動注入,將容器中已有的bean注入到使用@Autowired標(biāo)簽的對象中,可以設(shè)定是否必須注入,默認(rèn)為必須注入,如未能注入的情況下會產(chǎn)生報錯

源碼

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

@DependsOn

使用方式

使用在類、接口(包括注釋類型)或枚舉聲明之上,和方法之上

作用

進行注入bean的依賴設(shè)定,指定當(dāng)前類依賴某個或某些類

源碼

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {
    String[] value() default {};
}

@Component/@Controller/@Service/@Repository

使用方式

使用在類、接口(包括注釋類型)或枚舉聲明之上

作用

標(biāo)注對應(yīng)類要被注冊到容器中,當(dāng)被包掃描掃描后注入到容器中

源碼

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    String value() default "";
}

@Scope

使用方式

使用在類,接口,或者枚舉類上,也可以使用在方法上

作用

設(shè)定bean的作用域,默認(rèn)為單例singleton,可選擇為prototype原型模式,每次調(diào)用都有新的對象產(chǎn)生

源碼

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

    @AliasFor("scopeName")
    String value() default "";

    @AliasFor("value")
    String scopeName() default "";

    ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}

@Lazy

使用方式

使用在類,接口,或者枚舉類上,也可以使用在方法上,屬性,構(gòu)造器,

作用

設(shè)置bean為懶加載,而不是啟動容器后就加載

源碼

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
    boolean value() default true;
}

@PostConstruct和@PreDestroy

使用方式

使用在方法之上

作用

將標(biāo)注的方法設(shè)置為當(dāng)前bean的初始化方法和銷毀方法

源碼

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

@Value

使用方式

可以使用在屬性,方法,參數(shù),注釋之上

作用

為標(biāo)注屬性設(shè)置值

源碼

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {

    String value();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容