1. 代理
AOP是面向切面编程的意思,而AOP底层用到的设计模式就是代理,要深入学习AOP就很有必要来了解一下代理设计模式。
场景 : 我们需要在一个业务实现类HelloImpl的hello()方法的前后分别执行before() 和 after的监控。
public interface Hello{
public void say(String str);
}
public class HelloImpl implements Hello{
public void say(String str){
System.out.println("hello:"+ str);
}
}
有以下几种做法,每一种做法都是对前一种做法的提升。
1.1 写死代码
public class HelloImpl implements Hello{
public void say(String str){
before();
System.out.println("hello:"+ str);
after();
}
private void before(){
System.out.println("before hello");
}
private void after(){
System.out.println("before hello");
}
}
这种写死代码的缺点,就是与原有的业务代码耦合度高,需要动到原来的业务实现类的代码。
1.2 静态代理
保留原来的Hello接口和HelloImpl实现类,原封不动。 额外新增一个代理类HelloProxy来扩展额外的功能。
public class HelloProxy implements Hello{
private Hello hello;
public HelloProxy (){
hello = new HelloImpl();
}
private void before(){
System.out.println("before hello");
}
private void after(){
System.out.println("before hello");
}
@Overide
public void say(String str){
before();
hello.say(str);
after();
}
}
这就是静态代理,对原来的业务接口实现类进行二次包装实现,从而达到对原始业务实现方法hello()的前后扩展。
缺点:试想一下,如果有100个这个的业务类需要扩展同样的包装,就需要新建100个对应的代理类,这样就造成了代理类数量的无限膨胀的问题。
1.3 动态代理:JDK动态代理
JDK动态代理是JDK使用动态反射机制为我们提供的一个动态代理的实现方法,可有效解决静态代理遗留的代理类数量的无限膨胀问题。
public class JDKDynamicProxy implements InvocationHandler{
private Object target;//被代理的实现类
public JDKDynamicProxy(Object target){
this.target = target;
}
public <T> T getProxy(){
return <T> Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before(){
System.out.println("before hello");
}
private void after(){
System.out.println("before hello");
}
}
public class Client{
public static void main(String[] args){
Hello hello = new JDKDanamicProxy(new HelloImpl()).getProxy();
hello.say("Jack");
}
}
这样所有的代理类都合并到动态代理类中了,但这样子仍然存在一个问题:JDK给我提供的动态代理只能代理接口,而不能代理没有接口的类。有什么方法可以解决这个问题呢? 那就是CGLib动态代理。
1.4 动态代理:CGlib动态代理
CGLib动态代理是开源CGLib类库提供的动态代理机制,可以代理没有接口的类,有效弥补JDK动态代理的不足。
public class CGLibDynamicProxy implements MethodInterceptor{
private static CGLibDynamicProxy instance = new CGLibDynamicProxy();
private CGLibDynamicProxy(){}
pubilc static CGLibDynamicProxy getInstance(){
return instance;
}
@SuppressWarnings("unchecked")
public <T> T getProxy(Class<T> cls){
return (T) Enhancer.create(cls, this);
}
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable{
before();
Object result = proxy.invokeSuper(target, args);
after();
return result;
}
private void before(){
System.out.println("before hello");
}
private void after(){
System.out.println("before hello");
}
}
public class Client{
public static void main(String[] args){
HelloImpl hello = CGLibDynamicProxy.getInstance().getProxy(HelloImpl.class);
hello.say("Jack");
}
}
到此问题基本都解决了,以下图回顾总结一下: