动态代理与静态代理的区别?
静态代理需要手工编写代理类,代理类引用被代理对象。
动态代理是内存中构建的,不需要手动编写代理类。
代理概念
为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
静态代理类优缺点
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
静态代理
由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
动态代理
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
动态代理优点:
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强
byName:byname方式域属性自动注入,要求自动自动注入的Bean的id名称要与被注入的属性名相同。
byType:byType要求业务类中只能有一个和注入属性相同的属性。
代理是一种设计模式,对原有对象的行为进行增强。
代理模式(Proxy)为其他对象提供了一种代理以控制对这个对象的访问,代理模式在访问对象时引入一定程度的间接性,因为这种间接性可以附加多种用途。
代理模式的使用:
远程使用:为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实。
虚拟代理:是根据需要创建开销很大的对象,通过它来存放实例化需要很长世间的真实对象。
安全代理:控制真实对象的访问权限,一般用于对象应有不同的访问权限的时候。
智能代理:指调用真实对象的时候,代理处理另外一些事,如计算机真实对象的引用次数。
动态代理AOP:
(JDK) 本质:在内存中构建出接口的实现类
特点:被代理对象,必须有接口
(cglib) 本质:在内存中生成被代理类的子类
特点:可以在没有接口的情况下代理
对于不使用接口的业务类,无法使用JDK动态代理,cglib采用非底层的字节码技术,可以为一个类创建子类,解决无接口代理问题
静态代理:
public interface Subject { public String add(); }
public class ResouSubject implements Subject { public String add() { System.out.println("service add "); return ""; } }事务已开启!!public class ProxySubject implements Subject { //对象间交互 private Subject subject; public String add() { System.out.println("事务已开启!!"); return subject.add(); } public Subject getSubject() { return subject; } public void setSubject(Subject subject) { this.subject = subject; } }//静态代理,测试类 public class Subjectscatic { @Test public void stctic(){ //真实主题对象 Subject subject=new ResouSubject(); //代理对象 ProxySubject proxySubject=new ProxySubject(); proxySubject.setSubject(subject); proxySubject.add(); } }结果:
service add
---------------------------------------------------------------
JDK动态代理:
public interface Stuer { public String add(); public String edit(); }
public class StuerImpl implements Stuer { public String add() { System.out.println("===add==="); return "add"; } public String edit() { System.out.println("===edit==="); return "edit"; } }测试类:public class JDKTestdong { //动态JDK @Test public void testjdk(){ final Stuer use=new StuerImpl(); Stuer pro= (Stuer) Proxy.newProxyInstance(use.getClass().getClassLoader(), use.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("事务已开启了耶!!!"); method.invoke(use,args); return null; } }); pro.add(); pro.edit(); } }JDK动态测试结果:事务已开启了耶!!!
===add===
事务已开启了耶!!!
===edit===
-------------------------------------------------------------------------
//Cglib动态代理 public interface UserDao { public String add(); }public class IserDaoinpl implements UserDao { public String add() { System.out.println("add123456"); return "add"; } }//Cglib动态测试类 public class CliinTest { @Test public void fun(){ final UserDao udo=new IserDaoinpl(); //ENhancer对象 Enhancer enhancer=new Enhancer(); //在内存中构建业务类的子类 enhancer.setSuperclass(udo.getClass()); enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("事务已经开启了哦"); methodProxy.invoke(udo,objects); return null; } }); UserDao pro= (UserDao) enhancer.create(); pro.add(); } }//cglib动态测试结果:事务已经开启了哦
add123456
------------------------------------------------------------------------
经典AOP----异常:
public interface TherService { public void rend(); }public class SpringExction implements ThrowsAdvice { public void afterThrowing(Exception ex){ System.out.println("错误"); } }public class stuthrow implements TherService { //核心业务 public void rend() { int i=5/0; System.out.println("人生若是无误,铅笔何须橡皮!"); } }applicationContestSpringThrowing.xml<!--目标对象--> <bean id="stuthrow" class="cn.happy.SpringThrowing.stuthrow"></bean> <!--增强--> <bean id="SpringExction" class="cn.happy.SpringThrowing.SpringExction"></bean> <!--aop--> <bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="stuthrow"></property> <property name="interceptorNames" value="SpringExction"></property> </bean> </beans>AOP异常测试类:
public class SpringThrow { //异常 @Test public void throwing(){ ApplicationContext ctt=new ClassPathXmlApplicationContext("applicationContestSpringThrowing.xml"); TherService stu= (TherService) ctt.getBean("proxyService"); stu.rend(); } }---------------------------------------------------------经典AOP前置
public class SomeService { public void servicr(){ System.out.println("service------------111"); } }public class SAdaoimpl implements MethodBeforeAdvice { public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("=====前置====="); } }applicationContestSpringAop011.xml<!--目标对象--> <bean id="SAdaoimpl" class="cn.happy.SpringAdopBefore01.SomeService"></bean> <!--增强--> <bean id="sAdaoimpl" class="cn.happy.SpringAdopBefore01.SAdaoimpl"></bean> <!--aop--> <bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="SAdaoimpl"></property> <property name="interceptorNames" value="sAdaoimpl"></property> </bean>前置测试类:
public class SpringAdopTest011 { //前置 @Test public void testaop(){ ApplicationContext cts=new ClassPathXmlApplicationContext("applicationContestSpringAop011.xml"); SomeService service= (SomeService) cts.getBean("proxyService"); service.servicr(); } }
------------------------------------------------------------
经典AOP后置
public class afer { public void ter(){ System.out.println("+++++after++++"); } }
public class afteimpl implements AfterReturningAdvice { public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { System.out.println("--------后置--------"); } }applicationContestSpringAfter011.xml
<!--目标对象--> <bean id="afer" class="cn.happy.SpringAopAfter02.afer"></bean> <!--增强--> <bean id="afteimpl" class="cn.happy.SpringAopAfter02.afteimpl"></bean> <!--aop--> <bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="afer"></property> <property name="interceptorNames" value="afteimpl"></property> </bean>后置测试类:
public class SpringAopAfterTest { //后置 @Test public void testafter(){ ApplicationContext cts=new ClassPathXmlApplicationContext("applicationContestSpringAfter011.xml"); afer sf= (afer) cts.getBean("proxyService"); sf.ter(); } }------------------------------------------------------------------------
经典AOP环绕
public interface SomeService { public void doservice(); }
public class methservice implements SomeService { public void doservice() { System.out.println("人生若是无误,铅笔何须橡皮!"); } }public class MyMethodterpter implements MethodInterceptor { public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("=======before======="); methodInvocation.proceed(); System.out.println("========after======="); return null; } }applicationContestSpringhuanrao.xml<!--目标对象--> <bean id="methservice" class="cn.happy.huanrao.methservice"></bean> <!--增强--> <bean id="MyMethodterpter" class="cn.happy.huanrao.MyMethodterpter"></bean> <!--aop--> <bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="methservice"></property> <property name="interceptorNames" value="MyMethodterpter"></property> </bean>环绕测试类:
public class HuanRaotest { //环绕 @Test public void huanrao(){ ApplicationContext app=new ClassPathXmlApplicationContext("applicationContestSpringhuanrao.xml"); SomeService som= (SomeService) app.getBean("proxyService"); som.doservice(); } }