首先讲下需求,这是最近做的一个项目,提供一个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对象是空的