FactoryBean:以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的Id从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身, 如果要获取FactoryBean对象,可以在id前面加一个&符号来获取。
下面简单的分享下利用FactoryBean接口实现一个类似aop的功能
1.首先创建一个需要aop的类
public interface HelloWorldService {
void sayHelloWorld(String name);
void sayGood(String name);
void smile(String name);
}
2.实现上述接口,代码略
3.定义aop接口类
public interface HelloWorldAop {
/**
* 在执行方法之前执行的代码
*/
void doBefore(Object... args);
/**
* 在执行方法之后执行的代码
*/
void doAfter(Object... args);
}
4.写一个或多个实现类去实现上述接口,具体几个实现类取决于不同的业务需求
public class HelloWorldAopImpl implements HelloWorldAop {
public static final Logger log = LoggerFactory.getLogger(HelloWorldAopImpl.class);
/*
* (non-Javadoc)
* @see com.dingwang.aop.HelloWorldAop#doBefore()
*/
public void doBefore(Object... args) {
log.info("do before the method sayHello for " + args[0]);
}
/*
* (non-Javadoc)
* @see com.dingwang.aop.HelloWorldAop#doAfter()
*/
public void doAfter(Object... args) {
log.info("do after the method sayHello for " + args[0]);
}
}
5.核心部分,创建代理类HWFactoryBean,代理类实现FactoryBean和InitializingBean接口
/** 被代理对象实现的接口 */
private String interfaceName;
/** 被代理的对象 */
private Object target;
/** 生成的代理对象 */
private Object proxyObj;
/** 要处理的代理对象中的方法,若为空,则处理所有方法 */
private Map<String/* 代理对象的方法名 */, HelloWorldAop> proxyMethodMap;
public void afterPropertiesSet() throws Exception {
proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class[] { Class.forName(interfaceName) }, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
String methodName = method.getName();
log.info("method:" + method.getName());
//判断此方法是否需要做处理
if (proxyMethodMap != null && proxyMethodMap.containsKey(methodName)) {
//做before处理
proxyMethodMap.get(methodName).doBefore(args);
result = method.invoke(target, args);
//做after处理
proxyMethodMap.get(methodName).doAfter(args);
} else {
result = method.invoke(target, args);
}
return result;
}
});
log.info("afterPropertiesSet............");
}
上述片段可以看出代理类
HWFactoryBean实现InitializingBean,初始化时会去创建一个实例,这个实例是对被代理的类的包装,加了doBefore和doAfter处理,然后将其赋值给proxyObj,而对于实现FactoryBean接口的类,在根据beanId调用的时候,返回的对象实际上是getBoject(..)返回的对象,即proxyObj,从而实现对HelloWorldService中方法的织入
6.调用实例
public static void main(String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "classpath:spring-bean.xml" });
HelloWorldService hw = (HelloWorldService) context.getBean("proxyHW");
log.info("-----------------华丽的分割线-------------------------");
hw.sayHelloWorld("LiuBei");
log.info("-----------------华丽的分割线-------------------------");
hw.sayGood("CaoCao");
log.info("-----------------华丽的分割线-------------------------");
hw.smile("SunQuan");
HWFactoryBean hb = (HWFactoryBean) context.getBean("&proxyHW");
log.warn(hb.getClass().getName());
}
7.配置
<bean id="helloWorldService" class="com.dingwang.FactoryBean.Impl.HelloWorldServiceImpl"></bean>
<bean id="goodByeAop" class="com.dingwang.aop.Impl.GoodByeAopImpl"></bean>
<bean id="helloWorldAop" class="com.dingwang.aop.Impl.HelloWorldAopImpl"></bean>
<bean id="proxyHW" class="com.dingwang.FactoryBean.HWFactoryBean">
<property name="interfaceName" value="com.dingwang.FactoryBean.HelloWorldService"></property>
<property name="target" ref="helloWorldService"></property>
<property name="proxyMethodMap">
<!-- key: -->
<map>
<entry key="sayGood">
<ref bean="goodByeAop"/>
</entry>
<entry key="sayHelloWorld">
<ref bean="helloWorldAop"/>
</entry>
</map>
</property>
</bean>
输出: