- Aop:简称面向切面编程,这是Spring的一个关键性的组件。Spring Aop的出现是为了取代EJB中的事物机制,它有这种声明式的事务机制,Aop提供另外一种角度来思考程序结构,通过这种方式弥补了面对对象(OOP)的不足。
- 在实际开发过程中,往往常见Aop的需求:(1)比如写系统日志,便于我们查看系统的运行情况(2)安全校验,进行权限校验或者非空校验(3)性能优化(4)错误、异常处理
- Aop的使用特色:专门用于扩展系统功能,这样就不用去修改OOP编程已经写好的代码,符合高内聚的开发要求。
- 以下说明两种动态生成代理对象的方法
(1)jdk中有个著名的类:Proxy类,代理类,专门用来动态生成代理对象(面对接口编程)
-
/**
*创建一个User接口
*/public interface UserDao {
public void addUser();
public void queryUser();
}
-
/**
* 定义接口实现类,以下无具体实现代码,为了测试使用
* @author hp
*
*/
public class UserDaoImpl implements UserDao {@Override
public void addUser() {
System.out.println("--- adduser ----");}
@Override
public void queryUser() {
System.out.println("--- queryuser ----");}
}
-
/**
*
* 创建jdk代理工厂类,需要实现InvocationHandler这个接口
* @author hp
*
*/
public class ProxyFactory implements InvocationHandler{
//获取日志log,需要获取本类的路径
Logger log = Logger.getLogger("cn.neusoft.spring.proxy.ProxyFactory");
//需要先声明一个目标对象
private Object targetObject;
public Object getProxyObject(Object targetObject){
this.targetObject = targetObject;
/**
* 返回一个重构类对象(代理对象),其中三大参数:类加载器,类需要实现的接口,返回本类
* targetObject.getClass().getClassLoader():目标对象的类加载器,方便对目标对象进行改造
* targetObject.getClass().getInterfaces():代理对象需要实现和目标对象一样的接口,所以需要获取目标对象实现了哪 些接口
* this:代表当前对象
*/
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
}
@Override
//在invoke方法中可以方便的扩展目标对象的相关方法的功能
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
log.log(Level.INFO,"访问-----"+method.getName()+"开始");
//调用执行
Object result = method.invoke(this.targetObject, args);
log.log(Level.INFO,"访问-----"+method.getName()+"结束");
return result;
}}
-
/**
* 测试代理工厂类
* @author hp
*
*/
public class TestProxyFactory {public static void main(String[] args) {
//1.实例化化实现类对象
UserDao userDao = new UserDaoImpl();
//2.实例化抽象工厂
ProxyFactory pf = new ProxyFactory();
//通过抽象工厂,返回代理对象
UserDao userdao = (UserDao)pf.getProxyObject(userDao);
userdao.addUser();}
}
(2)万一是单例模式的话,面对对象编程实现代理工厂类的话,不能再用jdk实现,需要借助第三方jar包去实现
cglib的jar包以及asm的jar包实现(务必导入这两个包,必注意版本问题,可能有些版本会冲突,导致运行出错)
- /*
* 定义一个实现类EmpDaoImpl
*/
public class EmpDaoImpl {
public void deleteEmp(int empNo){
System.out.println("---deleteEmp-----");
}
public void queryEmp(){
System.out.println("---queryEmp-----");
}
}
- /**
* 定义CglibProxFactory类,来模拟Cglib包下代理工厂的写法
* @author hp - *
*/
public class CglibProxFactory implements MethodInterceptor{
//获取日志小log
Logger log = Logger.getLogger("cn.neusoft.spring.proxy.CglibProxFactory");
//声明一个对象
private Object taget;
//生成代理对象方法,这是cglib中跟jdk中不同的写法
public Object getProxObject(Object target){
this.taget=target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(taget.getClass());//设置taget这个类
enhancer.setCallback(this);//设置回调函数
return enhancer.create();//返回这个enhancer的类
}
@Override
public Object intercept(Object object, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
//获取方法中的参数
System.out.println("args"+Arrays.toString(args));
log.log(Level.INFO,"开始-----"+method.getName());
//打印第一个参数:会陷入死循环(可能为了防止观察它的具体信息)
//System.out.println("proxy:"+proxy);
System.out.println("方法名字"+method.getName());
log.log(Level.INFO,"结束-----"+method.getName());
//打印第四个参数:会陷入死循环(可能为了防止观察它的具体信息)
//System.out.println("methodProxy:"+methodProxy.getClass().getName());
return null;
}
} - /**
* 定义一个测试类TestCglibProxFactory
* @author hp
*
*/
public class TestCglibProxFactory {
public static void main(String args[]){
//注意这里实例化实现类,不再是接口类型
EmpDaoImpl empImpl = new EmpDaoImpl();
CglibProxFactory cglibProx = new CglibProxFactory();
EmpDaoImpl empImpProxDaoImpl= (EmpDaoImpl) cglibProx.getProxObject(empImpl);
empImpProxDaoImpl.deleteEmp(11);
}
}