动态代理

1   JDK动态代理    cglib动态代理

      

   先介绍jdk动态代理

   特点:代理目标对象必须有接口。

   实质:内存中构建出了接口的实现类。

   下面开始代码示例

   接口

  

public interface Isomeservice {
    public void Some();
}
public class SomeServiceImpl implements Isomeservice {
    public void Some() {
        System.out.println("do some===============");
    }
}

以上为实现类 

 1 public class texr {
 2 
 3     public static void main(String[] args) {
 4 
 5         final Isomeservice se=new SomeServiceImpl();
 6 
 7 
 8         Isomeservice proxy=(Isomeservice) Proxy.newProxyInstance(se.getClass().getClassLoader(),
 9                 se.getClass().getInterfaces(), new InvocationHandler() {
10                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
11 
12                         System.out.println("lalalaalal");
13                         method.invoke(se,args);
14                         return null;
15                     }
16                 });
17 
18 
19 
20         proxy.Some();
21     }
22 
23 }
View Code

这个就是实现方法  。 

lalalaalal
do some===============

以上是控制台,可以看出,我们实现了动态代理。  

第二个开始讲 cglib 动态代理   

  特点:在一类型没有接口的情况下进行代理。

  实质:内存中在构建了目标类型的子类。

  对于不使用接口的业务类,无法使用JDK动态代理,cglib采用底层的字节码技术,可以为一个类创建子类。

  现在开始代码示例 

public class SomeServiceImpl implements Isomeservice {
    public void Some() {
        System.out.println("do some===============");
    }
}

还是这个类 

public class text {
    public static void main(String[] args) {

        final SomeServiceImpl some=new SomeServiceImpl();

        Enhancer enhancer=new Enhancer();

        enhancer.setSuperclass(some.getClass());

        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("aaaaaaaa");
                methodProxy.invoke(some,objects);
                return null;
            }
        });

        SomeServiceImpl ss=  (SomeServiceImpl)enhancer.create();

        ss.Some();




    }
}

以上是实现了cglib动态代理,没有接口 

aaaaaaaa
do some===============

控制台也可以看出,这个成功了 

下面说下4种增强 

先说环绕 

以下开始代码示例

public class Cdd {

    public  void some(){

        //int i=5/0;
        System.out.println("dfdfdfdfdfd");

    }

}

先给出环绕增强的 类

public class Jack implements MethodInterceptor {
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {


        System.out.println("=====aa");


        methodInvocation.proceed();


        System.out.println("==============bb");

        return null;
    }
}
  methodInvocation.proceed(); 为隔开,前面的就为前置增强,后置的就为后置增强  

 

下面开始看配置文件 

  <bean id="Cdd" class="cn.autowired.entity.Cdd"></bean>

  <bean id="Jack" class="cn.autowired.entity.Jack"></bean>

    <bean id="Proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="Cdd"></property>
        <property name="interceptorNames" value="Jack"></property>
    </bean>

下面来说测试类

    @Test
    public void hh() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application-04.xml");

        Cdd c = (Cdd) context.getBean("Proxy");

        try {
            c.some();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

以下运行 ,结果

三月 10, 2018 9:27:20 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1517365b: startup date [Sat Mar 10 09:27:20 CST 2018]; root of context hierarchy
三月 10, 2018 9:27:20 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [application-04.xml]
=====aa
dfdfdfdfdfd
==============bb

这样就实现了前后置增强 

 下面来讲异常增强 。 

在使用类中出错来实现 

public class Cdd {

    public  void some(){

        int i=5/0;
        System.out.println("dfdfdfdfdfd");

    }

}

 这个运行时,铁定报错 

 现在来写异常增强 类 

 1  
 2 
 3 public class Expr implements ThrowsAdvice {
 4 
 5 public void afterThrowing(Exception e){
 6 
 7     System.out.println("网络异常");
 8 
 9 }
10 
11 
12 }
13  

这个实现以下throwsAdvice就行,不过他没有要你必须要实现的方法  

得自己手动写

现在来看小配置 

1  <bean id="Expr" class="cn.autowired.entity.Expr"></bean>
2 
3  <bean id="Proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
4         <property name="target" ref="Cdd"></property>
5         <property name="interceptorNames" value="Expr"></property>
6     </bean>

 现在来看测试类

    public void hh() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application-04.xml");

        Cdd c = (Cdd) context.getBean("Proxy");

        try {
            c.some();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

就是这样,异常增强就实现了

java.lang.ArithmeticException: / by zero
    at cn.autowired.entity.Cdd.some(Cdd.java:10)
    at cn.autowired.entity.Cdd$$FastClassBySpringCGLIB$$5f5b2599.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:125)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
    at cn.autowired.entity.Cdd$$EnhancerBySpringCGLIB$$1249e288.some(<generated>)
    at tt.hh(tt.java:269)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
网络异常

控制台也是铁定报错了 

现在来说小配置的用法 

    <bean id="Proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="Cdd"></property>
        <property name="interceptorNames" value="Expr"></property>
    </bean>

class,必须选对了,

 target 这一行,连接增强

   ref,为使用增强类的bean节点的id,

  interceptorNames 为增强类的节点 , value为增强类的bean节点的id 

前后我就不说了 ,和之前写的博客一样 , 写出后 

还是按照上面的来写 ,  

1 为 bean节点   2 为 使用节点 

现在来说 代理工厂 

使用类依旧不变 

Cdd  

节点也就增加了 

    <bean id="Dg" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="Befo"></property>
        <property name="mappedNames" value="some"></property>
     </bean>

class中的东西是使用工厂的东西 

1 advice  为使用的增强。

2 mappedNames 为实用的方法。

使用时 

<bean id="Proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="Cdd"></property>
        <property name="interceptorNames" value="Dg"></property>
    </bean>

把Value改成以上bean的id,这就好了 some为Cdd的方法

现在看测试 

    @Test
    public void hh() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application-04.xml");

        Cdd c = (Cdd) context.getBean("Proxy");

        try {
            c.some();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
三月 10, 2018 10:25:03 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1517365b: startup date [Sat Mar 10 10:25:03 CST 2018]; root of context hierarchy
三月 10, 2018 10:25:03 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [application-04.xml]
aaaaaaaaa
dfdfdfdfdfd

现在看见控制台也就实现了这个

  

  

原文地址:https://www.cnblogs.com/LWLDD/p/8537476.html