关于反射和动态代理的使用
动态代理的方式简化业务层的大量重复代码
Interface
package com.xwl;
/**
* 动态代理
* @author Administrator
*
*我们可以使用动态代理的方式简化销售公司的大量重复代码
*
*/
//苹果需要生产四种产品 交给中国工厂
interface Iphone{
public void product6s();
public void product6Plus();
public void product7();
public void productX();
}
service
//生产厂商生产苹果手机
class Phone implements Iphone{
public void product6s() {
System.out.println("6s");
}
public void product6Plus() {
System.out.println("6Plus");
}
public void product7() {
System.out.println("7");
}
public void productX() {
System.out.println("X");
}
}
业务
//销售公司Agent 宣传 销售
class Agent{
//首先我需要手机
private Iphone phone;
public Iphone getPhone() {
return phone;
}
public void setPhone(Iphone phone) {
this.phone = phone;
}
// **1.宣传 我们 2.生产(phone.product6s()) 3.销售发货**
public void product6s(){
System.out.println("宣传");
phone.product6s();//生产的什么?
System.out.println("销售和发货");
}
// **1.宣传 我们 2.生产(phone.product6Plus()) 3.销售发货**
public void product6Plus(){
System.out.println("宣传");
phone.product6Plus();
System.out.println("销售和发货");
}
// **1.宣传 我们 2.生产(phone.product7()) 3.销售发货**
public void product7(){
System.out.println("宣传");
phone.product7();
System.out.println("销售和发货");
}
// **1.宣传 我们 2.生产(phone.productX()) 3.销售发货**
public void productX(){
System.out.println("宣传");
phone.productX();
System.out.println("销售和发货");
}
}
public class Test_fanse {
public static void main(String[] args) {
}
}
我们可以通过动态代理的方式简化销售公司的任务,动态代理的实现有两种一种是JDK的原生方式,另一种是封装了(字节码处理框架ASM)的CGLIB动态代理实现。
首先我们要细化上面的代码
苹果生产厂商提供的生产苹果手机的接口(规范)
package com.xwl;
public interface PhoneService {
//苹果生产四种产品 交给中国工厂
public void product6s();
public void product6Plus();
public void product7();
public void productX();
}
中国富士康给出了实现制造出来实现(实现)
package com.xwl;
public class PhoneServiceImpl implements PhoneService {
public void product6s() {
System.out.println("6s");
}
public void product6Plus() {
System.out.println("6Plus");
}
public void product7() {
System.out.println("7");
}
public void productX() {
System.out.println("X");
}
}
一、JDK实现动态代理(销售公司)
代理对象JdkProxy :
package com.xwl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler{
//要代理的对象
private Object target;
public JdkProxy(Object target) {
super();
this.target = target;
}
public JdkProxy() {
super();
}
//给一个代理对象
public Object getProxy(){
return Proxy.newProxyInstance(Thread.currentThread()
.getContextClassLoader(), target.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("宣传");
Object reslut = method.invoke(target, args);
System.out.println("销售和发货");
return reslut;
}
}
生产出了一个phone7开始宣传
package com.xwl;
public class TestJdk {
public static void main(String[] args) {
PhoneService phoneService = new PhoneServiceImpl();
JdkProxy jdkProxy = new JdkProxy(phoneService);
PhoneService proxy = (PhoneService) jdkProxy.getProxy();
proxy.product7();
}
}
CGLIB实现动态代理
代理对象CglibProxy :
package com.xwl;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println("宣传");
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("销售和发货");
return result;
}
}
生产出来了一个6s开始宣传:
package com.xwl;
import org.springframework.cglib.proxy.Enhancer;
public class TestCglib {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PhoneServiceImpl.class);//继承被代理类
enhancer.setCallback(new CglibProxy());//设置回调
PhoneServiceImpl PhoneProxy = (PhoneServiceImpl) enhancer.create();//生成代理对象
PhoneProxy.product6s();
}
}
总结
动态代理的好处是什么?
Java动态代理的优势是实现无侵入式的代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情(甚至不去执行这个方法就可以)。
动态代理和静态代理的区别?
1.静态代理类:由程序员创建或者由第三方工具生成,再进行编译;在程序运行之前,代理类的.class文件已经存在了。
动态代理类:在程序运行时,通过反射机制动态生成。
2.静态代理类通常只代理一个类。动态代理类通常代理接口下的所有类。
3.静态代理事先知道要代理的是什么。动态代理事先不知道要代理的是什么,只有在运行的时候才能确定。
4.动态代理的调用处理程序必须事先InvocationHandler接口,及使用Proxy类中的newProxyInstance方法动态的创建代理类。
5.Java动态代理只能代理接口,要代理类需要使用第三方的CLIGB等类库。
JDK动态代理和CGLIB动态代理的区别?
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
Enhancer
Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是类他都能正常工作。