作用:保护原对象;可以增加原对象的功能.
静态代理:在编译时就获得代理对象,这叫静态代理.
动态代理:在运行时通过反射获得代理对象,叫动态代码.
注意:AOP的底层用的是动态代理.
/**
* 男孩的业务父接口
* @auth ljc
*/
public interface BoyFriendService {
/**
* 寻找女朋友的方法
*/
public void findGirlFriend();
}
他有一个正在找女朋友的方法
/**
* 男孩的业务实现类
* @auth ljc
*/
public class BoyFriendServiceImpl implements BoyFriendService{
/**
* 寻找女朋友的方法
*/
@Override
public void findGirlFriend() {
System.out.println("正在寻找女朋友...");
}
}
但总是找不到,于是他找了个媒婆帮他找
这媒婆就是他的代理,媒婆跟女孩说
我这一个优质男孩(前置增强:在切点(原方法)执行之前执行增强处理代码)
正在寻找女朋友…(执行原方法)
他有八套房,一辆劳斯莱斯幻影(后置增强:在切点(原方法)执行之后执行增强处理代码.)
/**
* jdk动态代理处理类
* @auth ljc
*/
public class JdkProxy implements InvocationHandler {
/**
* 声明被代理的对象
*/
Object target;
/**
* 通过构造方法将原对象传过来
* @param ob
*/
public JdkProxy(Object ob){
this.target=ob;
}
/**
* 代理方法
* @param proxy 原对象的代理对象
* @param method 原方法的反射对象
* @param args 原方法的参数列表
* @return Object
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我这一个优质男孩");
//用原方法的反射对象调用原方法
Object result= method.invoke(target,args);
System.out.println("他有八套房,一辆劳斯莱斯幻影");
return result;
}
}
但这媒婆有一个缺点,就是男孩女孩两人见面,必须要男孩他爹来,不然不给面
/**
* 测试类
* @auth ljc
*/
public class JkdTest1{
public static void main(String[] args) {
//创建原对象
BoyFriendService boyFriend=new BoyFriendServiceImpl();
//创建jdk动态代理的处理器
JdkProxy jdkProxy=new JdkProxy(boyFriend);
//创建jdk代理对象,第一个参数是类加载器,第二个参数是原对象的父接口反射对象,第三个参数是动态代理处理对象
BoyFriendService boyFriendProxy= (BoyFriendService) Proxy.newProxyInstance(JkdTest1.class.getClassLoader(),boyFriend.getClass().getInterfaces(),jdkProxy);
//用jdk代理对象调用方法
boyFriendProxy.findGirlFriend();
}
}
/**
* 男孩的业务实现类
* @auth ljc
*/
public class BoyFriendServiceImpl implements BoyFriendService{
/**
* 寻找女朋友的方法
*/
@Override
public void findGirlFriend() {
System.out.println("正在寻找女朋友...");
}
}
他找了一个媒婆
媒婆跟女孩说
我这一个优质男孩(前置增强:在切点(原方法)执行之前执行增强处理代码)
正在寻找女朋友…(执行原方法)
他有八套房,一辆劳斯莱斯幻影(后置增强:在切点(原方法)执行之后执行增强处理代码.)
/**
* cglib动态代码的处理类
* @auth ljc
*/
public class CgLibProxy implements MethodInterceptor {
/**
* 声明原类的子类对象
*/
public Enhancer en=new Enhancer();
/**
* 声明一个方法获得cglib动态代码的子类的代理对象
* @param clazz 原对象的反射对象
* @return Object
*/
public Object getCgLibProxy(Class clazz){
//将原类设为子类对象的处器对象的父类
en.setSuperclass(clazz);
//将当前处理器类的对象设为子类处器对象
en.setCallback(this);
//通过子类对象的创建子类的代理对象
return en.create();
}
/**
* 代理方法
* @param o 原对象
* @param method 子类方法反射对象
* @param objects 方法参数
* @param methodProxy 代理对象的代理方法反射对象
* @return Object
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("我这一个优质男孩");
//调用原方法
Object result= methodProxy.invokeSuper(o,objects);
System.out.println("他有八套房,一辆劳斯莱斯幻影");
return result;
}
}
但不同的是,媒婆不找男孩他爹了,她给男孩找了个儿子(编不下去了,哈哈哈,有违常理)
/**
* 测试类
* @auth ljc
*/
public class JkdTest1{
public static void main(String[] args) {
//创建处理器对象
CgLibProxy cgLibProxy=new CgLibProxy();
//获得原类的子类的代理对象
BoyFriendServiceImpl boyFriendProxy= (BoyFriendServiceImpl) cgLibProxy.getCgLibProxy(BoyFriendServiceImpl.class);
//用子类的代理对象调用原类的方法
boyFriendProxy.findGirlFriend();
}
}
2.Spring在选择用JDK还是CGLiB代理时是看Bean有没有实现接口;实现接口了,Spring用JDK的动态代理;没有实现接口,Spring就用CGlib代理