概念:委托一個代理類對另一個類進行控制(代理類中有被代理類的對象,同時可以在代理類中增強)
使用場景:aop(可以控制被代理類是否被調用,是否被代理)。
優點:1.確定被代理類的隐秘性
2.降低耦合性(不用挨個加需要增強的方法)
缺點:類數量的增多,結構更複雜。
類圖:

靜态代理
1 靜态代理:靜态代理就是把增強的方法寫在代理的類中,在編譯時就确定了,這樣耦合性比較高,除了方法量級較小或者增強的方法固定,其他情況不推薦。
subject接口
1. public interface PlayLol{
2. public void plya();
3. }
realSubject
1. public class IsPlay implements PlayLol{
2. public void play() {
3. System.out.println("開始玩");
4. }
5. }
proxy
1. public class ProxySubject implements PlayLol{
2.
3. private PlayLol playLol;
4. //關鍵,将被代理對象傳進來
5. public ProxySubject(final PlayLol playLol) {
6. this.playLol = playLol;
7. }
8.
9. public void play() {
10. System.out.println("打開電腦");
11. //可以增加控制 ,可以不讓他玩。。。
12. subject.play();
13. System.out.println("15投");
14. }
15. }
調用
1. public class MainClass {
2. public static void main(String[] args) {
3. PlayLol playLol = new IsPlay();
4. playLol.paly();
5.
6. System.out.println("============");
7.
8. ProxySubject proxySubject = new ProxySubject(playLol);
9. proxySubject.paly();
10. }
11. }
2.動态代理:
JDK代理
代理類
1. public class ProxyHandler implements InvocationHandler {
2.
3. private Object object;
4.
5. public DynamicProxyHandler(final Object object) {
6. this.object = object;
7. }
8.
9. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
10. System.out.println("先開電腦");
11. Object result = method.invoke(object, args);
12. System.out.println("關電腦");
13. return result;
14. }
15. }
調用:
1. public class MainClass {
2. public static void main(String[] args) {
3. PlayLol subject = new IsPlay();
4. /**
5. * ClassLoader loader:指定目前目标對象使用的類加載器,擷取加載器的方法是固定的
6. * Class<?>[] interfaces:指定目标對象實作的接口的類型,使用泛型方式确認類型
7. * InvocationHandler:指定動态處理器,執行目标對象的方法時,會觸發事件處理器的方法
8. * 都是固定寫法
9. */
10. PlayLol proxySubject = (PlayLol) Proxy.newProxyInstance(PlayLol.class.getClassLoader(),
11. new Class[]{PlayLol.class},
12. new ProxyHandler(subject));
13. proxySubject.play();
14. }
CGLib動态代理
如果被代理類沒有接口不可以使用jdk動态代理
被代理類
1. public class IsPlay{
2. public void play() {
3. System.out.println("開始玩");
4. }
5. }
1. public class CglibProxy implements MethodInterceptor {
2. private Object target;//業務類對象,供代理方法中進行真正的業務方法調用
3.
4. //相當于JDK動态代理中的綁定
5. public Object getInstance(Object target) {
6. this.target = target; //給業務對象指派
7. Enhancer enhancer = new Enhancer(); //建立加強器,用來建立動态代理類
8. enhancer.setSuperclass(this.target.getClass()); //為加強器指定要代理的業務類(即:為下面生成的代理類指定父類)
9. //設定回調:對于代理類上所有方法的調用,都會調用CallBack,而Callback則需要實作intercept()方法進行攔
10. enhancer.setCallback(this);
11. // 建立動态代理類對象并傳回
12. return enhancer.create();
13. // 以上都是固定寫反
14. }
15. // 實作回調方法
16. public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
17. System.out.println("開電腦");
18. proxy.invokeSuper(obj, args); //調用業務類(父類中)的方法
19. System.out.println("關電腦");
20. return null;
21. }
22. }
1. public class MainClass {
2. public static void main(String[] args) {
3. IsPlay play= new IsPlay();
4. CglibProxy cglibProxy = new CglibProxy();
5. IsPlay realSubjectProxy =
6. (IsPlay) cglibProxy.getInstance(play);
7. realSubjectProxy.play();
8. }
9. }
引用:CGLIB建立的動态代理對象比JDK建立的動态代理對象的性能更高,但是CGLIB建立代理對象時所花費的時間卻比JDK多得多。是以對于單例的對象,因為無需頻繁建立對象,用CGLIB合适,反之使用JDK方式要更為合适一些。同時由于CGLib由于是采用動态建立子類的方法,對于final修飾的方法無法進行代理。