随手记录2:spring 中的自定义的FactoryBean的使用
简介
工作面试中一定会碰到spring的FactoryBean 的相关问题;
简单的说就是一个工厂,来生成我们的目标对象并且交给spring管理;
当然还可以通过FactoryBean类通过代理实现增强我们的目标对象;
项目是基于springboot来实现的如果还不是很了解springboot的配置可以参考一下本人之前的一下文章内容
资源的链接内容
一.实现FactoryBean创建bean交给spring管理
1. 目标对象我们的UserService
public class UserService {
private String userName;
public UserService() {}
private UserService(String userName) {
this.userName = userName;
}
public static UserService getInstance(String userName){
return new UserService(userName);
}
public String say(String detail) {
System.out.println("用户{"+userName+"} say{"+detail+"}");
return "say执行完毕";
}
}
UserService是我们的目标对象;
2.UserServiceFactoryBean 目标对象的工厂类
/**
* UserService的工厂类
* 初始化后通过getObject获取到我们的目标对象内容;
* getObjectType 返回的目标对象的类型
* isSingleton 标识目标对象是否是单例的
* @author khy
* @createTime 2020年9月2日下午1:47:10
*/
public class UserServiceFactoryBean implements FactoryBean<UserService> {
private String userName;
public UserServiceFactoryBean() {}
public UserServiceFactoryBean(String userName) {
this.userName = userName;
}
@Override
public UserService getObject() throws Exception {
return UserService.getInstance(userName);
}
@Override
public Class<?> getObjectType() {
return UserService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
3.FactoryBeanConfig 配置UserServiceFactoryBean工厂类的
// 通过Bean注解将初始化UserServiceFactoryBean 然后将该工厂获取的UserService也交给spring管理
@Bean
public UserServiceFactoryBean createUserFactoryBean (){
UserServiceFactoryBean bean = new UserServiceFactoryBean("candy");
return bean;
}
完成上述的配置之后就完成了UserService 通过UserServiceFactoryBean 做到交给spring管理了
我们想要使用UserService 只需要通过@Autowired 注入就可以直接使用;
4.FactoryController 中注入 UserService对象;
@Autowired
private UserServiceFactoryBean factoryBean;
@Autowired
private UserService userService;
@RequestMapping("/test")
public String test() throws Exception{
String say = userService.say("注入的userService成功");
say = factoryBean.getObject().say("注入的userService的factoryBean成功");
return "执行完毕了";
}
通过请求当前接口打印出来的结果
二.通过FactoryBean对目标对象进行功能增强;
首选我们的目标类UserService 我们在类上通过@Service("userService")
确保可以通过@Autowired将目标对象注入
然后在修改一下UserServiceFactoryBean 中的代码内容;
1.UserServiceImpl
@Service("userService")
public class UserServiceImpl implements UserService {
private String userName="默认小康康";
public String say(String detail) {
System.out.println("用户{"+userName+"} say{"+detail+"}");
return "say执行完毕";
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
因为需要代理所以和之前的代码不太一样添加了一个接口类
2.UserServiceFactoryBean
public class UserServiceFactoryBean implements FactoryBean<UserService>,InitializingBean {
/**被代理的对象(需要增强的接口)*/
private UserService userService;
/**被代理的对象(需要增强的接口)*/
private UserService proxyUserServie;
public UserServiceFactoryBean() {}
public UserServiceFactoryBean(UserService userService) {
this.userService = userService;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
proxyUserServie = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
new Class[] { Class.forName("com.khy.service.UserService") }, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("method:" + method.getName());
System.out.println("说话开始前先打招呼");
Object result = method.invoke(userService, args);
System.out.println("说话结束后再说拜拜");
return result;
}
});
}
@Override
public UserService getObject() throws Exception {
return proxyUserServie;
}
@Override
public Class<?> getObjectType() {
return UserService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
实现 InitializingBean 接口 的afterPropertiesSet 方法里面将我们的目标对象转换成我们的代理对象;并且在目标对象的目标方法执行前后可以做一切增强方法的操作(日志打印/校验参数等…)
然后FactoryBean 的getObject 返回的是我们的代理对象;
3.FactoryBeanConfig 配置;
@Configuration
public class FactoryBeanConfig {
@Autowired
private UserService userService;
@Bean("proxyUserServie")
public UserServiceFactoryBean createUserFactoryBean (){
UserServiceFactoryBean bean = new UserServiceFactoryBean(userService);
System.out.println("createUserFactoryBean初始化");
return bean;
}
}
因为在UserService中 通过注解@Service("userService") 通过
@Autowired
private UserService userService;
获取到的是原先的目标对象,然后按照UserServiceFactoryBean 的构造要求传递目标对象
@Bean("proxyUserServie") 通过工厂类返回的代理对象的beanName是proxyUserServie
4.FactoryController
@RestController
@RequestMapping("/factory")
public class FactoryController {
@Autowired
private UserServiceFactoryBean factoryBean;
@Autowired
@Qualifier("userService")
private UserService userService;//这个是原目标对象
@Autowired
@Qualifier("proxyUserServie")
private UserService proxyUserServie;//这个是通过FactoryBean生成的代理对象;
@RequestMapping("/test")
public String test() throws Exception{
String say = userService.say("原目标对象userService执行");
System.out.println("//");
say = proxyUserServie.say("代理对象proxyUserServie执行");
//因为通过factoryBean获取到的还是代理对象所以是一样的效果
say = factoryBean.getObject().say("FactoryBean获取到的代理对象proxyUserServie执行");
return "执行完毕了"+say;
}
}
下面是对应的打印内容;
结论
虽然controller中通过
@Autowired
@Qualifier("userService")
private UserService userService;
@Autowired
@Qualifier("proxyUserServie")
private UserService proxyUserServie;
注入的都是 UserService对象; 但是原来的方法不受影响
代理的方法执行之前或者之后我们可以做一下额外的操作
总结
FactoryBean 就是Spring的工厂类初始化我们指定的目标对象,交给spring管理;