随手记录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管理;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值