spring源码实战应用,对外提供的starter中如何强制实现某个接口

首先讲下需求,这是最近做的一个项目,提供一个SDK让其他业务系统使用,但是因为项目内部使用了Shiro权限框架,获取用户信息的时候,定义了一个UserService接口,用户在使用我们提供的框架时,必须要实现UserService接口,所以最终需求就是,需要强制用户在自己的代码模块实现UserService接口

需要考虑以下几个点:

1、我们提供的SDK是属于用户自己模块之外的,所以要实现检查类的自动装配

IUserService接口是要强制被实现的接口
public interface IUserService {

    void getName();

}
CheckInterfaceFactoryPostProcessor该类是检查接口是否被实现后置处理器,其中最主要的是通过getBeanNamesForType()方法判断接口被实现的个数,其实也可以用getBean(Object T)方法判断,但是会存在一个问题,后续讲解
public class CheckInterfaceFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        String[] beanNamesForType = beanFactory.getBeanNamesForType(IUserService.class);
        if (beanNamesForType.length == 0) {
            throw new RuntimeException("Interface UserService is not be implemented ! ");
        }

    }

}

2、第二步,配置META-INF下的spring.factories文件,实现CheckInterfaceFactoryPostProcessor类的自动装配

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.itao.boot.loctor.CheckInterfaceFactoryPostProcessor

第三步测试:直接启动项目就会报错 Interface UserService Is Not Be Implemented ! 

第四步:实现IUserService接口,同时,依赖注入User对象

@Component
public class User {

    public User() {
        System.out.println("用户创建");
    }

    public void printName(){
        System.out.println("user创建");
    }

}
@Service
public class DefaultUserServiceImpl implements IUserService, BeanPostProcessor {

    @Autowired
    private User user;

    @PostConstruct
    public void init() {
        System.out.println(user + " user ...... ");
    }

    @Override
    public void getName() {
        user.printName();
    }
}

在此启动项目:观察日志发现,执行了初始化方法,也就是说DefaultUserServiceImpl接口被注册到IOC容器当中,并且此时通过@Autowired注解依赖注入的User对象也被实例化了,此时-强制实现某个接口的功能就已经被实现了 !!! ;

但是如果我们在判断接口是否被实现的时候用的是getBean方法 ,会发生什么意外呢?

public class CheckInterfaceFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

//        String[] beanNamesForType = beanFactory.getBeanNamesForType(IUserService.class);
//        if (beanNamesForType.length == 0) {
//            throw new RuntimeException("Interface UserService Is Not Be Implemented ! ");
//        }

        //  提前实例化的bean不会再走正常流程进行属性填充
        try {
            IUserService bean = beanFactory.getBean(IUserService.class);
        } catch (RuntimeException runtimeException) {
            throw new RuntimeException("Interface UserService Is Not Be Implemented ! ");
        }

    }

}

将实现类的@Service注解注释掉

//@Service
public class DefaultUserServiceImpl implements IUserService, BeanPostProcessor {

    @Autowired
    private User user;

    @PostConstruct
    public void init() {
        System.out.println(user + " user ...... ");
    }

    @Override
    public void getName() {
        user.printName();
    }
}

控制台依旧会打印报错,因为没有找到接口的bean定义信息

但是此时把@Service注解加上的话,那么就会有问题,在此启动不会报错  但是初始化方法@PostConstruct不会被执行,同时,@Autowired进行依赖注入的时候,也是为null的

@Component
public class User {

    public User() {
        System.out.println("用户创建");
    }

    public void print(){
        System.out.println("user创建");
    }

}
@Service
public class DefaultUserServiceImpl implements IUserService, BeanPostProcessor {

    @Autowired
    private User user;

    @PostConstruct
    public void init() {
        System.out.println(user + " user ...... ");
    }

    @Override
    public void getName() {
        user.print();
    }
    
}
@RequestMapping("/user")
@RestController
public class UserController {

    @Autowired
    private IUserService userService;

    @GetMapping("/getUserName")
    public void test1() {
        userService.getName();
    }

}

最后一步测试:http://localhost:8080/user/getUserName 直接在浏览器输入即可;

此时观看后台日志,User对象是空的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值