1.静态代理简单实现
①首先需要一个接口,执行类和代理类都实现这个接口
public interface Person {
public void sell();
}
②写一个卖房子的户主类,实现上面的接口
public class Seller implements Person {
@Override
public void sell() {
System.out.println("卖房子");
}
}
③写一个代理类(可以理解为中介),也实现上面的接口
public class Porxyer implements Person {
private Seller seller;
@Override
public void sell() {
if(seller==null){
seller=new Seller();
}
preSell();
seller.sell();
afterSell();
}
private void afterSell() {
System.out.println("卖完了,办手续");
}
private void preSell() {
System.out.println("卖之前,谈价格");
}
}
④测试类
public class test {
public static void main(String[] args) {
Person person=new Porxyer();
person.sell();
}
}
可以在卖房子之前和之后加上想要执行的方法
2.动态代理简单实现
①一个接口
public interface Person {
public void sell();
}
②一个具体执行类来实现上面的接口
public class Seller implements Person {
@Override
public void sell() {
System.out.println("卖房子");
}
}
③一个代理类,继承InvocationHandler接口,并重写其invoke方法,和静态代理不同的地方是,动态代理类它的成员变量类型为Object,也就是说提前是不知道要代理哪个类的,这也就是动态代理的好处,传入不同的类就可以代理不同的类,其中的"method.invoke(realObject,args)“是调用realObject中的方法,具体调用哪个方法看测试类怎么写,在这个方法调用的前后可以添加"增强”。最后的createProxy方法是为了创建一个代理类。
public class DynamicPorxyer implements InvocationHandler {
private Object realObject;
public DynamicPorxyer(Object realObject){
this.realObject=realObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("卖房子前先谈价格!");
method.invoke(realObject,args);
System.out.println("卖完房子办手续~");
return null;
}
public Object createProxy(){
return Proxy.newProxyInstance(realObject.getClass().getClassLoader(),realObject.getClass().getInterfaces(),this);
}
}
④一个测试类
测试类,首先创建一个接口对象指向具体执行类的引用,其次创建一个代理类对象,把上面的接口对象传入其构造函数,然后调用代理类的createProxy方法来创建一个真正的代理类,把这个代理类赋值给上面的接口对象,再使用接口对象调用方法时就可以有增强了
public class test {
public static void main(String[] args) {
Person person=new Seller();
DynamicPorxyer dynamicPorxyer=new DynamicPorxyer(person);
Object object=dynamicPorxyer.createProxy();
person= (Person) object;
person.sell();
}
}
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP。
3、如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换。
总结来看就是,cglib可以针对目标对象实现接口或者不实现接口都行,而要想使用JDK的动态代理,必须要目标对象实现接口