文章目录
实例:
public class UserDaoImpl implements UserDao{
/**
* 业务逻辑和非业务逻辑混在一起,导致代码不易维护,
* 解决办法动态代理或者aop
*/
@Override
public void addUser() {
//记录日志
MyLog.doLog(this.getClass());
// 业务代码
System.out.println("添加学生数据");
//提交事务
MyTransaction.doTransaction(this.getClass());
}
在我们的编程过程中,遇到很多中这样的情况,非业务逻辑和业务代码混在一起,并且每个方法都是这样,导致代码的耦合性很强,并且维护性可读性降低。那有没有一种方法可以解决这种问题呢?那就是动态代理,用代理对象来解决这个问题。
JDK动态代理
public class UserDaoImpl implements UserDao{
/**
* 业务逻辑
*/
@Override
public void addUser() {
// 业务代码
System.out.println("添加学生数据");
}
public class MyLog {
public static void doLog(Class<?> clazz){
System.out.println("记录日志"+clazz.getName());
}
}
public class MyTransaction {
public static void doTransaction(Class<?> clazz){
System.out.println("提交事务"+clazz.getName());
}
}
/**
*jdk 动态代理拦截器
* 代理类实现InvocationHandler接口
*
* @author 李娜
* @version 0.0.1
* @since 0.0.1 2019-04-04
*/
public class MyInvocationHandler implements InvocationHandler {
private Object target;
/**
* 通过构造方法将要增强的类对象传入
*/
public MyInvocationHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
//记录日志
MyLog.doLog(target.getClass());
//业务处理
Object invoke=method.invoke(target,args);
//处理事务
MyTransaction.doTransaction(target.getClass());
return invoke;
}
}
在调用代理对象的addUser方法时,进入到了拦截器的invoke方法体
拦截器中invoke方法体的内容就是代理对象方法体的内容
/*
* 测试动态代理
*/
@Test
public void testProxy(){
//创建目标类对象
UserDaoImpl userDao=new UserDaoImpl();
//创建代理
UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new MyInvocationHandler(userDao));
userDaoProxy.addUser();
}
打印结果:
CGLIB 动态代理
package com.cj.study.proxycglib;
public interface PersonService {
public String savePerson();
public void updatePerson();
public void deletePerson();
}
package com.cj.study.proxycglib;
public class PersonServiceImpl implements PersonService{
@Override
public String savePerson() {
System.out.println("添加");
return "保存成功!";
}
@Override
public void updatePerson() {
System.out.println("修改");
}
@Override
public void deletePerson() {
System.out.println("删除");
}
}
package com.cj.study.proxycglib;
public class MyTransaction {
public void beginTransaction(){
System.out.println("开启事务 ");
}
public void commit(){
System.out.println("提交事务");
}
}
package com.cj.study.proxycglib;
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 PersonServiceInterceptor implements MethodInterceptor{
//目标类
private Object target;
//增强类
private MyTransaction myTransaction;
//构造函数注入目标类和增强类
public PersonServiceInterceptor(Object target,MyTransaction myTransaction){
this.target = target;
this.myTransaction = myTransaction;
}
public Object createProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(this.target.getClass());
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
myTransaction.beginTransaction();
Object returnValue = arg1.invoke(this.target, arg2);
myTransaction.commit();
return returnValue;
}
}
package com.cj.study.proxycglib;
import org.junit.Test;
public class ProxyTest {
@Test
public void test(){
Object target = new PersonServiceImpl();
MyTransaction myTransaction = new MyTransaction();
PersonServiceInterceptor interceptor = new PersonServiceInterceptor(target, myTransaction);
PersonService personService =(PersonService) interceptor.createProxy();
String returnValue = (String)personService.savePerson();
System.out.println(returnValue);
}
}
运行结果:
通过上面两种代理可以实现目标方法的增强,但是问题是太过于麻烦,我们需要自己去生成代理对象,自己手写拦截器,在拦截器里自己手动的去把要增强的内容和目标方法结合起来,这用起来还是有点繁琐。
那spring Aop就不需要自己手写了,aop会自动创建代理对象,并按照你的配置把增强的内容和目标方法结合起来。spring Aop 的原理下节分享~