专栏首页学习笔记持续记录中...Spring - 通过注解配置Bean(8)

Spring - 通过注解配置Bean(8)

扫描组件

Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件。

特定组件包括: Component:基本注解,标识了一个受Spring管理的组件 Respository:标识持久层组件 Service: 标识服务层(业务层)组件 Controller:标识表现层组件

对于扫描到组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写;

注解中通过value属性值标识组件的名称

使用注解后,还需要在Spring的配置文件中声明<context:component-scar>: base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有的类;当需要扫描多个包时,可以使用逗号隔开 resource-pattern 扫描特定的类而非基包下的所有类

目录结构

// UserRepository
public interface UserRepository {
    void save();
}
// UserRepositoryImpl
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
    @Override
    public void save() {
        System.out.println("UserRepository Save...");
    }
}
// UserController
@Controller
public class UserController {

    public void execute(){
        System.out.println("UserController execute... ");
    }
}
// UserService
@Service
public class UserService {
    public void add(){
        System.out.println("UserService add......");
    }
}
// TestObject
@Component
public class TestObject {
}
// Main
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        TestObject to = (TestObject)ctx.getBean("testObject");
        System.out.println(to);
        UserController tuserController = (UserController)ctx.getBean("userController");
        System.out.println(tuserController);
        UserService userService = (UserService)ctx.getBean("userService");
        System.out.println(userService);
        UserRepository userRepository = (UserRepository)ctx.getBean("userRepository");
        System.out.println(userRepository);
    }
}
// xml
<!--指定Spring IOC容器扫描的包 -->
<context:component-scan base-package="com.sangyu.test05.annotation"/>
// resource-pattern 指定扫描的资源
<context:component-scan base-package="com.sangyu.test05.annotation" resource-pattern="repository/*.class"/>

<context:include-filter>: 子节点表示要包含的目标类 <context:exclude-filter>: 子节点表示要排除在外的目标类 <context:component-scar>: 下可以拥有若干个 <context:include-filter><context:exclude-filter>子节点

类别

示例

说明

annotation

com.test.XxxAnntation

所有标注了XxxAnnotation的类。该类型采用目标类是否标注了某个注解进行过滤

assinable

com.test.XxxService

所有继承或扩展XxxService的类,该类型采用目标类是否继承或扩展某个特定类进行过滤

<!--type="annotation" 该类型采用目标类是否标注了某个注解进行过滤-->
<!--context:exclude-filter 子节点指定排除哪些指定表达式的组件-->
<context:component-scan base-package="com.sangyu.test05.annotation">
        <context:exclude-filter expression="org.springframework.stereotype.Repository" type="annotation"/>
</context:component-scan>

<!--context:include-filter 子节点指定包含哪些表达式的组件,该子节点需要use-default-filters配合使用-->
<context:component-scan
        base-package="com.sangyu.test05.annotation"
        use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

<!--type="assignable" 所有继承或扩展XxxService的类,该类型采用目标类是否继承或扩展某个特定类进行过滤 -->
<context:component-scan base-package="com.sangyu.test05.annotation">
    <context:exclude-filter type="assignable" expression="com.sangyu.test05.annotation.repository.UserRepository"/>
</context:component-scan>

<context:component-scan base-package="com.sangyu.test05.annotation" use-default-filters="false">
    <context:include-filter type="assignable" expression="com.sangyu.test05.annotation.repository.UserRepository"/>
</context:component-scan>

使用@Autowired自动装配Bean

构造器,普通字段(即使是非public)一切具有参数的方法都可以应用@Autowired注解

默认情况下,所有使用@Autowired注解的属性都需要被设置,当Spring找不到匹配的Bean装配属性时,会抛出异常

// UserService
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    public void add() {
        System.out.println("UserService add......");
        userRepository.save();
    }
}
// 另一种方式
@Service
public class UserService {
    private UserRepository userRepository;
    @Autowired
    public void setUserRepository(UserRepository userRepository){
        this.userRepository = userRepository;
    }
    public void add() {
        System.out.println("UserService add......");
        userRepository.save();
    }
}
// UserController
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void execute() {
        System.out.println("UserController execute... ");
        userService.add();
    }
}
// Main
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserController userController = (UserController) ctx.getBean("userController");
        System.out.println(userController);
        userController.execute();
    }
}

若某一属性允许不被设置,可以设置@Autowired注解的required属性为false

// Main
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserRepository userRepository = (UserRepository)ctx.getBean("userRepository");
        System.out.println(userRepository);
    }
}
// TestObject
//@Component 注释掉
public class TestObject { }
// 实现类
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
    @Autowired(required = false)
    private TestObject testObject;
    @Override
    public void save() {
        System.out.println("UserRepository Save...");
        System.out.println(testObject);
    }
}
// 接口
public interface UserRepository {
    void save();
}

两个类实现一个接口的情况

// 接口
public interface UserRepository {
    void save();
}

// 实现类1
@Repository("userRepository") // 两个类实现一个接口 ,默认会按照设置的名字去查找实现类
public class UserRepositoryImpl implements UserRepository {
    @Autowired(required = false)
    private TestObject testObject;
    @Override
    public void save() {
        System.out.println("UserRepository Save...");
        System.out.println(testObject);
    }
}

// 实现类2
@Repository
public class UserJdbcRepository implements UserRepository {
    @Override
    public void save() {
        System.out.println("UserJdbcRepository save....");
    }
}
// Main
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService)ctx.getBean("userService");
        System.out.println(userService);
        userService.add();
    }
}
// 另一种方式:使用@Qualifier
@Service
public class UserService {
    @Autowired
    @Qualifier("userJdbcRepository")
    private UserRepository userRepository;
    public void add() {
        System.out.println("UserService add......");
        userRepository.save();
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • TestNG用法概括

    应用场景:将通用的功能抽取并封装起来,在方法中使用注解@BeforeSuite和@AfterSuite,在测试类中继承这个类,测试类在运行前会先运行@Befor...

    桑鱼
  • Spring - 泛型依赖注入(9)

    桑鱼
  • Java-字符串

    String是不可变的,String类中每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象,以包含修改后的字符串内容。而最初的S...

    桑鱼
  • Java一些常见的坑

    总是觉得自己Java基础还是不行,需要恶补。今天偶然mark了一本《Java解惑》,其中以端程序的方式罗列了95个即常见又不常见的xian(坑)jing(儿),...

    cxuan
  • Java原型模式(prototype)

      prototype模式也就是原型模式,是javaGOF23种设计模式中的一种,我们在学习spring的时候在bean标签的学习中碰到过,所以本文来给大家介绍...

    用户4919348
  • 第22次文章:建造者模式+原型模式

    这周我们就可以把GOFO23设计模式中的创建型模式全部介绍完了!后面在项目里面可以试一下啦!

    鹏-程-万-里
  • 设计模式之模板方法模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决...

    低调小熊猫
  • Java-面向对象(多态)

    编译时看的都是左边,运行时成员方法看的是右边,其他(成员变量和静态方法)看的都是左边

    DataScience
  • TestNG用法概括

    应用场景:将通用的功能抽取并封装起来,在方法中使用注解@BeforeSuite和@AfterSuite,在测试类中继承这个类,测试类在运行前会先运行@Befor...

    桑鱼
  • SpringMVC快速使用AOP

    最近突然想到了AOP编程,于是在自己的SpringMVC小项目中引入了。AOP一般用来做些什么呢?这里简单的使用AOP做拦截日志,来介绍下在SpringMVC中...

    幽鸿

扫码关注云+社区

领取腾讯云代金券