如:有一个添加用户的方法:add(),在添加之前和添加之后要做分别做两中日志记录。
1.静态代理:
1-1.继承的写法:
//接口:
package com.watermelon.statics.proxy;
public interface UserService {
public void add();
}
//添加用户的实现类
package com.watermelon.statics.proxy;
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("新增add");
}
}
//代理类
package com.watermelon.statics.proxy;
public class UserServiceProxy extends UserServiceImpl{
@Override
public void add() {
System.out.println("add 之前日志2");
System.out.println("add 之前日志1");
super.add();
System.out.println("add 之后日志1");
System.out.println("add 之后日志2");
}
}
//测试方法
package com.watermelon.statics.proxy;
public class Main {
public static void main(String[] args) {
UserService userServiceProxy = new UserServiceProxy();
userServiceProxy.add();
}
}
//测试结果
//add 之前日志2
//add 之前日志1
//新增add
//add 之后日志1
//add 之后日志2
缺点:不够灵活,1.每次增加日志需修改代理类。2.若其他方法下需要同样的日志记录,则需要新增代理类。
2-2.聚合的方式:类内部有其他类的变量。
//接口
package com.watermelon.statics.proxy;
public interface UserService {
public void add();
}
//实现类
package com.watermelon.statics.proxy;
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("新增add");
}
}
//代理类1:日志1
package com.watermelon.statics.proxy;
public class UserServiceProxy2 implements UserService{
private UserService tagert;
public UserServiceProxy2(UserService tagert) {
super();
this.tagert = tagert;
}
@Override
public void add() {
System.out.println("add 之前日志1");
tagert.add();
System.out.println("add 之后日志1");
}
}
//代理类2:日志2
package com.watermelon.statics.proxy;
public class UserServiceProxy3 implements UserService{
private UserService tagert;
public UserServiceProxy3(UserService tagert) {
super();
this.tagert = tagert;
}
@Override
public void add() {
System.out.println("add 之前日志2");
tagert.add();
System.out.println("add 之后日志2");
}
}
//测试类
package com.watermelon.statics.proxy;
public class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserServiceProxy2 userServiceProxy = new UserServiceProxy2(userService);
UserServiceProxy3 userServiceProxy3= new UserServiceProxy3(userServiceProxy);
userServiceProxy3.add();
}
}
测试结果同上。
和继承的方式比:新增日志记录不用修改代理类源码,直接新增代理类。
缺点:若要给其他的方法新增日志记录,则还是需要新增更多的代理类。
2.jdk动态代理。
//接口
package com.watermelon.de.proxy;
public interface UserService {
public void add();
}
//实现类
package com.watermelon.de.proxy;
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("新增add");
}
}
//代理工厂类 生成代理类 生成日志记录2代理类
package com.watermelon.de.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class UserServiceProxyFactory1 implements InvocationHandler{
private Object tagert;
public MyTwoInvocationHandeler(Object tagert) {
super();
this.tagert = tagert;
}
public Object getProxy(){
ClassLoader loader = tagert.getClass().getClassLoader();
Class<?>[] interfaces = tagert.getClass().getInterfaces();
return Proxy.newProxyInstance(loader, interfaces, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("之前日志2");
Object result = method.invoke(tagert, args);
System.out.println("之后日志2");
return result;
}
}
//代理工厂类 生成代理类 生成日志记录2代理类
package com.watermelon.de.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class UserServiceProxyFactory2 implements InvocationHandler{
private Object tagert;
public MyTwoInvocationHandeler(Object tagert) {
super();
this.tagert = tagert;
}
public Object getProxy(){
ClassLoader loader = tagert.getClass().getClassLoader();
Class<?>[] interfaces = tagert.getClass().getInterfaces();
return Proxy.newProxyInstance(loader, interfaces, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("之前日志2");
Object result = method.invoke(tagert, args);
System.out.println("之后日志2");
return result;
}
}
//测试类User类
package com.watermelon.de.proxy;
public class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
//UserServiceProxyFactory1 代理工厂类
UserServiceProxyFactory1 proxyFactory1 = new UserServiceProxyFactory1 (userService);
UserService userServiceproxy = (UserService) proxyFactory1.getProxy();
UserServiceProxyFactory2 proxyFactory2 = new UserServiceProxyFactory2(userServiceproxy);
UserService userServiceProxy1 = (UserService) proxyFactory2.getProxy();
userServiceProxy1.add();
}
}
//测试结果
之前日志2
之前日志1
新增add
之后日志1
之后日志2
在比如,我现在有个部门类有个update方法也要添加同样的两种日志记录
//部门接口
package com.watermelon.de.proxy;
public interface DepartmentService {
public int update();
}
//实现类
package com.watermelon.de.proxy;
public class DepartmentServiceImpl implements DepartmentService{
@Override
public int update() {
System.out.println("修改 update");
return 1;
}
}
//测试类
package com.watermelon.de.proxy;
public class Main {
public static void main(String[] args) {
DepartmentService departmentService = new DepartmentServiceImpl();
UserServiceProxyFactory1 proxyFactory1 = new UserServiceProxyFactory1 (departmentService);
DepartmentService departmentServiceProxy1 = (DepartmentService) proxyFactory1.getProxy();
UserServiceProxyFactory2 proxyFactory2 = new UserServiceProxyFactory2 (departmentServiceProxy1);
DepartmentService departmentServiceProxy2 = (DepartmentService) proxyFactory2.getProxy();
departmentServiceProxy2.update();
}
}
结论:使用动态代理每种日志记录可以灵活配置,分开添加。没新增一种日志记录,只需要新增一种代理类的生成类。
生成动态代理类的步骤:
1.添加InvocationHandler接口。实现重写public Object invoke(Object proxy, Method method, Object[] args)
方法。
2.添加一个private Object tagert;
变量、并重写带tagert变量的构造方法。
3.新增一个返回代理类的方法;通过Proxy.newProxyInstance(loader, interfaces, this);
方法返回代理类。
4.cglib动态代理
不用和jdk动态地理一样需要实现同样的接口。直接生成类的动态代理类。
package com.watermelon.cglibproxy;
public class UserServiceImpl {
public void add()
{
System.out.println("add loading...");
}
}
CglibFactory 代理工厂类
package com.watermelon.cglibproxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibFactory implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 拦截所有目标类方法的调用
* obj 目标类的实例
* m 目标方法的反射对象
* args 方法的参数
* proxy代理类的实例
*/
@Override
public Object intercept(Object obj, Method m, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("日志开始...");
//代理类调用父类的方法
proxy.invokeSuper(obj, args);
System.out.println("日志结束...");
return null;
}
}
测试方法:
public static void main(String[] args) {
UserServiceImpl userServiceImpl= new UserServiceImpl();
CglibFactory cglibFactory = new CglibFactory();
UserServiceImpl userServiceImplProxy = (UserServiceImpl)cglibFactory.getProxy(userServiceImpl.getClass());
userServiceImplProxy.add();
}
需要引入cglib-nodep-2.2.jar