java相关

spring-ioc基础学习(3)基于JavaConfig的配置

2020-06-28  本文已影响0人  xywh

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

主要目标

JavaConfig的引入

spring从3.0版本引入JavaConfig提供配置功能,就可以使用JavaConfig替代xml文件进行配置,从4.0开始支持springboot后,springboot完全采用JavaConfig的方式进行开发配置

JavaConfig的使用

1)构建spring项目

<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>
@Configuration
public class IocJavaConfig {}
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
mysql.username=mall
mysql.password=mall
mysql.url=jdbc:mysql://192.168.1.150:3306/mall
mysql.driver=com.mysql.jdbc.Driver

2)进行类的装载配置

    /**
     *@Bean 将一个类的实例,注册到容器中成为一个容器中的bean被调用
     * @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);
    }
@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;
    }
}
@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("创建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();
    }
    /**
     * 内部bean的相互调用直接使用方法
     * @Bean可以设置多个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;
    }

测试

    /**
     * 测试内部bean的相互调用直接使用方法
     */
    @Test
    public void test03(){
        User user = context.getBean("userwx",User.class);
        User user2 = context.getBean(User.class);
        System.out.println(user);
    }
public class Wife extends Person{
    public Wife() {
        System.out.println("创建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);
    }

就像在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

使用方式

使用在类、接口(包括注释类型)或枚举声明之上

作用

用作标识配置类,替换spring的xml配置文件,作用等价于<beans>标签,在其中可以进行的操作:

  1. 声明要注册的类 @Bean
  2. 导入其他配置文件 @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>标签,用来将一个实例对象注入到容器中,可以进行的操作有:

  1. 设定类的生命周期 initMethod,destroyMethod
  2. 设置别名 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

使用方式

使用在类、接口(包括注释类型)或枚举声明之上

作用

引入指定的类,可以引入多个,以及可以引入第三方包,用于将相关的类直接注册到容器中

源码

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

@ComponentScan

使用方式

使用在类、接口(包括注释类型)或枚举声明之上

作用

扫描定义的包路径,将包路径中进行使用@Component相关注解标注的文件,注册到容器中,可以设定扫描包中的加载方式是否为懒加载,设置过滤,扫描或不扫描某些类,配置

源码

@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

使用方式

使用在类、接口(包括注释类型)或枚举声明之上

作用

导入外部的配置文件

源码

@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

使用方式

使用在构造器,方法,形参,字段声明(包括枚举常量),注释声明之上

作用

自动注入,将容器中已有的bean注入到使用@Autowired标签的对象中,可以设定是否必须注入,默认为必须注入,如未能注入的情况下会产生报错

源码

@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的依赖设定,指定当前类依赖某个或某些类

源码

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

@Component/@Controller/@Service/@Repository

使用方式

使用在类、接口(包括注释类型)或枚举声明之上

作用

标注对应类要被注册到容器中,当被包扫描扫描后注入到容器中

源码

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

@Scope

使用方式

使用在类,接口,或者枚举类上,也可以使用在方法上

作用

设定bean的作用域,默认为单例singleton,可选择为prototype原型模式,每次调用都有新的对象产生

源码

@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

使用方式

使用在类,接口,或者枚举类上,也可以使用在方法上,属性,构造器,

作用

设置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

使用方式

使用在方法之上

作用

将标注的方法设置为当前bean的初始化方法和销毁方法

源码

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

@Value

使用方式

可以使用在属性,方法,参数,注释之上

作用

为标注属性设置值

源码

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

    String value();
}
上一篇 下一篇

猜你喜欢

热点阅读