动态代理
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 }
这个就是实现方法 。
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
现在看见控制台也就实现了这个