一、JDK
- 核心思想:
原始类和代理类实现相同的接口
使用JDK自带api创建动态代理
public class JDKTest{public static void main(String[] args){// 获取原始对象UserService userService = new UserServiceImpl();ClassLoader classLoader = JDKTest.class.getClassLoader();Class<?>[] interfaces = userService.getClass().getInterfaces();InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("====执行原始方法之前====");// 运行原始方法Object ret = method.invoke(userService, args);System.out.println("====执行原始方法之后====");return ret;}};UserService userServiceProxy = (UserService)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);userServiceProxy.register(new User());userServiceProxy.login("zhl", "123");}
}
- 类加载器的作用(ClassLoader)
类加载器把对应类的字节码文件(.class)加载到JVM,创建这个类的Class对象,进而创建这个类的对象。
动态字节码技术没有创建代理类的源文件和字节码文件,但是需要创建动态代理类的对象,所以需要借用一个类加载器。 - interfaces
原始类实现的接口 - InvocationHandler
为原始类中的原始方法添加额外功能
二、Cglib
- 核心思想:
代理类继承原始类
使用Cglib创建动态代理,创建过程大致和JDK方式类似
public class CglibTest {public static void main(String[] args) {// 原始对象UserService userService = new UserService();Enhancer enhancer = new Enhancer();// 为动态代理类设置类加载器enhancer.setClassLoader(CglibTest.class.getClassLoader());// 设置原始类为父类,添加额外功能enhancer.setSuperclass(userService.getClass());MethodInterceptor interceptor = new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("----------cglib before--------");Object ret = method.invoke(userService, args);System.out.println("----------cglib after--------");return ret;}};// callback <===> invocationHandlerenhancer.setCallback(interceptor);// 创建代理对象UserService serviceProxy = (UserService) enhancer.create();serviceProxy.login("zzz", "222");serviceProxy.register(new User());}
}
三、BeanPostProcessor
Spring工厂如何加工原始对象?
思路分析:
简单代码实现:
public class ProxyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {InvocationHandler invocation = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("--------核心功能之前---------");Object ret = method.invoke(bean, args);System.out.println("--------核心功能之后---------");return ret;}};return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(),invocation);}
}
<bean id="userService" class="com.zhl.factory.UserServiceImpl"/>
<!--对当前配置文件中的所有bean进行加工-->
<bean id="proxyBeanPostProcessor" class="com.zhl.factory.ProxyBeanPostProcessor"/>
这里的实现比较粗糙,没有引入切入点,对整个Spring工厂中的bean都进行了加工。