从反射说起
反射技术应用广泛,使用反射可以实现类的配置化,Spring IoC的基本原理也是如此
在java 中反射是通过包java.lang.reflect.*来实现的
package com.lean.ssm.chapter2.reflect;
public class ReflectServiceImpl {
public void sayHello(String name){
System.out.println("Hello "+name);
}
}
反射生成对象
public ReflectServiceImpl getInstance(){
ReflectServiceImpl obj=null;
try {
obj=(ReflectServiceImpl) Class
.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl")
.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
编写测试
@Test
public void testSayHello() {
new ReflectServiceImpl().sayHello("lucas");
getInstance().sayHello("lucas li");
}
构建方法含有参数
package com.lean.ssm.chapter2.reflect;
public class ReflectServiceImpl2 {
private String name;
public ReflectServiceImpl2(String name) {
this.name = name;
}
public void sayHello(){
System.out.println("Hello "+this.name);
}
}
反射生成对象
public ReflectServiceImpl2 getInstance2(){
ReflectServiceImpl2 obj=null;
try {
obj = (ReflectServiceImpl2) Class
.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl2")
.getConstructor(String.class)
.newInstance("张三");
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
反射方法
public Object reflectMethod(){
Object obj=null;
ReflectServiceImpl target=new ReflectServiceImpl();
try {
Method method=ReflectServiceImpl.class
.getMethod("sayHello", String.class);
obj=method.invoke(target, "李四");
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
反射生成对象和反射调度方法
/**通过反射,生成的对象,调用的方法,方法的入参都可以实现配置化
* @return
*/
public Object reflect(){
ReflectServiceImpl obj=null;
Object ret=null;
try {
obj=(ReflectServiceImpl) Class
.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl")
.newInstance();
Method method=obj.getClass().getMethod("sayHello", String.class);
ret = method.invoke(obj, "王五");
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
动态代理
在java中有多种动态代理技术,比如JDK,CGLIB,Javasisst,ASM,其中最常用的是JDK自带的动态代理和CGLIB(一个第三方库)的动态代理,目前Spring常用JDK和CGLIB,Mybatis还使用了Javassist。
JDK动态代理
jdk的动态代理是包java.lang.reflect.*提供的,它必须借助一个接口来生成代理
package com.lean.ssm.chapter2.reflect;
public interface HelloWorld {
public void sayHelloWorld();
}
实现类
package com.lean.ssm.chapter2.reflect;
public class HelloWorldImpl implements HelloWorld {
@Override
public void sayHelloWorld() {
System.out.println("Hello World.");
}
}
代理逻辑
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyExample implements InvocationHandler{
//真实对象
private Object target=null;
public Object bind(Object obj){
this.target=obj;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法...");
System.out.println("在调度真实对象之前的服务");
Object invoke = method.invoke(target, args);//相当于调用sayHelloWorld方法
System.out.println("在调用真实对象之后的服务");
return invoke;
}
}
测试
/**
* JDK动态代理
*/
@Test
public void testJdkProxy(){
JdkProxyExample jdk=new JdkProxyExample();
HelloWorld proxy=(HelloWorld) jdk.bind(new HelloWorldImpl());
proxy.sayHelloWorld();
}
@Test
public void testSayHello() {
new ReflectServiceImpl().sayHello("lucas");
getInstance().sayHello("lucas li");
getInstance2().sayHello();
reflectMethod();
reflect();
}
输出
进入代理逻辑方法...
在调度真实对象之前的服务
Hello World.
在调用真实对象之后的服务
CGLIB动态代理
在一些不能提供接口的环境中,无法使用JDK的动态代理,只能采用其他第三方的技术,比如CGLIB,他的优势在于无需提供接口,只要一个一般的类(非抽象的类)。
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxyExample implements MethodInterceptor{
public Object getProxy(Class cls){
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(cls);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
System.out.println("在调用真实对象之前");
Object ret = methodProxy.invokeSuper(proxy, args);
System.out.println("在调用真实对象之后");
return ret;
}
}
测试
/**
* CGLIB动态代理
*/
@Test
public void TestCglibProxy(){
CglibProxyExample cglib=new CglibProxyExample();
ReflectServiceImpl proxy = (ReflectServiceImpl) cglib.getProxy(ReflectServiceImpl.class);
proxy.sayHello("熊二");
}
输出
在调用真实对象之前
Hello 熊二
在调用真实对象之后