1.代理模式(静态代理)
代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理。
静态代理由 业务实现类、业务代理类 两部分组成。业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截、过滤、预处理,主要是在方法中首先进行预处理动作,然后调用业务实现类的方法,还可以规定调用后的操作。我们在需要调用业务时,不是直接通过业务实现类来调用的,而是通过业务代理类的同名方法来调用被代理类处理过的业务方法。
UserDao.java
package com.wuhaitao.spring.demo1;
public interface UserDao {
public void save();
}
UserDaoImpl.java
package com.wuhaitao.spring.demo1;
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("用户被保存了");
}
}
UserProxy.java
package com.wuhaitao.spring.demo1;
public class UserProxy implements UserDao {
//组合一个业务实现类对象来进行真正的业务方法的调用
private UserDaoImpl userDaoImpl;
public UserProxy(UserDaoImpl userDaoImpl) {
this.userDaoImpl = userDaoImpl;
}
@Override
public void save() {
System.out.println("保存用户的预处理");
userDaoImpl.save();
System.out.println("保存用户后的操作");
}
}
SpringTest.java
package com.wuhaitao.spring.demo1;
import org.junit.Test;
public class SpringTest {
@Test
public void demo1() {
UserDaoImpl dao = new UserDaoImpl();
UserProxy userProxy = new UserProxy(dao);
userProxy.save();
}
}
静态代理的缺点很明显:一个代理类只能对一个业务接口的实现类进行包装,如果有多个业务接口的话就要定义很多实现类和代理类才行。而且,如果代理类对业务方法的预处理、调用后操作都是一样的(比如:调用前输出提示、调用后自动关闭连接),则多个代理类就会有很多重复代码。这时我们可以定义这样一个代理类,它能代理所有实现类的方法调用:根据传进来的业务实现类和方法名进行具体调用。——那就是动态代理。
2.JDK动态代理 (必须是实现接口的类,才能使用.并且,如果业务实现类中新增了接口中没有的方法,这些方法是无法被代理的(因为无法被调用)。)
UserDao.java
package com.wuhaitao.spring.demo2;
public interface UserDao {
public void save();
public void update();
public void delete();
public void select();
}
UserDaoImpl.java
package com.wuhaitao.spring.demo2;
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("用户被保存了");
}
@Override
public void update() {
System.out.println("用户信息更改了");
}
@Override
public void delete() {
System.out.println("用户被删除了");
}
@Override
public void select() {
System.out.println("查找用户的信息");
}
}
JdkProxy.java
package com.wuhaitao.spring.demo2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler{
//这其实业务实现类对象,用来调用具体的业务方法
private UserDao userDao;
public JdkProxy(UserDao userDao) {
this.userDao = userDao;
}
public UserDao createProxy() {
//通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
//创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this);
return userDaoProxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("save".equals(method.getName())) {
System.out.println("增强了");
return method.invoke(userDao, args);
}
return method.invoke(userDao, args);
}
}
SpringTest.java
package com.wuhaitao.spring.demo2;
import org.junit.Test;
public class SpringTest {
@Test
public void test() {
UserDao userDao = new UserDaoImpl();
UserDao proxy = new JdkProxy(userDao).createProxy();
proxy.save();
proxy.delete();
proxy.select();
proxy.update();
}
}
3.Cglib动态代理
cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。
UserDaoImpl.java
package com.wuhaitao.spring.demo3;
public class UserDaoImpl {
public void save() {
System.out.println("用户被保存了");
}
public void update() {
System.out.println("用户信息更改了");
}
public void delete() {
System.out.println("用户被删除了");
}
public void select() {
System.out.println("查找用户的信息");
}
}
CglibProxy.java
package com.wuhaitao.spring.demo3;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private UserDaoImpl userDaoImpl;
public CglibProxy(UserDaoImpl userDaoImpl) {
this.userDaoImpl = userDaoImpl;
}
//使用cglib产生代理的方法
public UserDaoImpl creqateProxy() {
//创建cglib的核心类对象
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(userDaoImpl.getClass());
//设置回调
enhancer.setCallback(this);
//创建代理对象
UserDaoImpl proxy = (UserDaoImpl) enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if("save".equals(method.getName())) {
System.out.println("增强了。。。。");
return methodProxy.invokeSuper(proxy, args);
}
return methodProxy.invokeSuper(proxy, args);
}
}
SpringTest.java
package com.wuhaitao.spring.demo3;
import org.junit.Test;
public class SpringTest {
@Test
public void test() {
UserDaoImpl userDaoImpl = new UserDaoImpl();
UserDaoImpl userDaoImplProxy = new CglibProxy(userDaoImpl).creqateProxy();
userDaoImplProxy.save();
userDaoImplProxy.delete();
userDaoImplProxy.update();
userDaoImplProxy.select();
}
}