Spring框架两大核心原理:AOP和IOC,IOC Inversion of control 用来解决依赖关系,通过工厂模式实现。
AOP Aspect of programming 通过动态代理实现。
1. 定义接口
/**
* 用户服务接口
* @author lingsun
*
*/
public interface UserService {
public String getName();
public Integer getAge();
}
/**
* 用户服务实现类
* @author sunling3
*
*/
public class UserServiceImpl implements UserService {
@Override
public String getName() {
System.out.println( "---- GetName" );
return "Sun";
}
@Override
public Integer getAge() {
System.out.println( "---- GetAge" );
return 18;
}
}
2. 方法一:反射实现
/**
* 反射实现动态代理
* @author lingsun
*
*/
public class MyInvocationHandler implements InvocationHandler {
private Object target;
MyInvocationHandler(){
super();
}
MyInvocationHandler( Object target ){
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 只拦截getName
if( method.getName() == "getName" ){
System.out.println( "------- before------->" );
Object result = method.invoke( target, args);
System.out.println( "<------- after--------" );
return result;
}else{
Object result = method.invoke( target, args );
return result;
}
}
/**
* main
* @param args
*/
public static void main(String[] args) {
// 接口
UserService service = new UserServiceImpl();
InvocationHandler handler = new MyInvocationHandler( service );
// 注入代理
UserService userServie = (UserService)Proxy.newProxyInstance(service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
handler);
// 代理对象实现了UserService接口(2),能动态生成UserService对象
System.out.println("Proxy: " + userServie.getClass().getName());
// 委托代理调用 --- 动态代理
userServie.getName();
userServie.getAge();
}
}
执行结果:
Proxy: com.sun.proxy.$Proxy0 ------- before-------> ---- GetName <------- after-------- ---- GetAge
上述userService并不是UserServiceImpl类,而是com.sun.proxy.$Proxy0,它是jvm运行时动态生成的一个对象。
2.1 InvocationHandler源码
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
// 查找或生成代理类
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// 通过反射获取构造函数并生成代理实例
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
}
}
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// 查找缓存是否存在,否则通过ProxyClassFactory生成
return proxyClassCache.get(loader, interfaces);
}
核心实现在ProxyClassFactory中,该类通过反射方式来构建类。
3. 方法二:cglib实现
Java动态代理需实现一个或多个接口,比较麻烦。CGLIB可以在不实现接口前提下,生成代理类。CGLIB 底层通过小而快字节码处理框架ASM来转换字节码并生成新的类。
/**
* CgLib实现动态代理
* @author lingsun
*
*/
public class CgLibProxy implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if( method.getName() == "getName" ){
System.out.println( "---------before "+ methodProxy.getSuperName() + "----->");
Object ol = methodProxy.invokeSuper(obj, args);
System.out.println( "<---------after "+ methodProxy.getSuperName() + "-----");
return ol;
}
else{
Object ol = methodProxy.invokeSuper(obj, args);
return ol;
}
}
/**
* main
* asm在内存中动态生成代理类
* 注:http://asm.ow2.org/
* Spring容器代替工厂,Spring AOP代替JDK动态代理,让面向切面编程更容易实现
* 在Spring的帮助下轻松添加,移除动态代理,且对源代码无任何影响
*
* @param args
*/
public static void main(String[] args) {
CgLibProxy proxy = new CgLibProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass( UserServiceImpl.class);
enhancer.setCallback(proxy); // 设置回调
// 实例通过Enhancer创建
UserService service = (UserService)enhancer.create();
System.out.println( "Proxy: " + service );
service.getName();
service.getAge();
}
}
执行结果:
Proxy: com.jd.proxy.UserServiceImpl$$EnhancerByCGLIB$$a129aaba@41906a77 ---------before CGLIB$getName$0-----> ---- GetName <---------after CGLIB$getName$0----- ---- GetAge
参考链接: