两种类型AOP:静态AOP和动态AOP。
静态代理:
代理对象与被代理对象必须实现同一个接口。
demo:
动态代理:
动态代理区别于静态带来实现的地方在于织入过程是在运行时动态进行的。自己实现一般实现java.lang.reflect.InvocationHandler接口。
例子:
------------------------------------------------------------------
利用ProxyFactory连接CGLIB简单实现AOP:
加入包aopalliance.jar\cglib-nodep-2.1_3.jar
demo:
------------------------------------------------------------------
代理
1.代理解决什么问题,为已存在的目标类的方法增加一些系统功能。如果采用工厂模式和配置文件进行管理,以后也很容易就可以去掉增加的功能。
2.静态代理类的工作原理,太多静态代理类,还有什么意思?jvm可以帮我们创建代理类,这就是动态代理类。
3.让jvm创建动态代理类,我们需要给它提供哪些信息?
让jvm帮我们创建一个类,我们需要为它提供哪些信息呢?a.有哪些方法,即告诉它实现哪些接口;b.产生的类必须有个妈妈,即类加载器对象;c.它生成的类中的方法的代码是怎样的,需我告诉它,我把我的代码写在一个约定好了接口的对象的方法中,把对象传给它,它调用我的方法,即相当于插入了我的代码。
4.写程序的步骤:
1). 快速演示动态代理的效果
2).可以接收外面传入的目标
3).最优雅的方式,接收目标同时返回代理,让调用者更懒惰,更方便,调用者甚至不用接触任何代理的API。
一点小心得:静态方法中也可以定义内部类,只是内部类中不能方法外部类的成员变量。
静态代理:
代理对象与被代理对象必须实现同一个接口。
demo:
- packagecn.partner4java.proxy.staticproxy;
- /**
- * 静态代理,统一接口
- * @author partner4java
- *
- */
- publicinterfaceIHello {
- /**
- * 可以带来的统一方法
- * @param name
- */
- publicvoidhello(String name);
- }
- packagecn.partner4java.proxy.staticproxy;
- /**
- * 被代理的对象,需要借助代理对象加入日志
- * @author partner4java
- *
- */
- publicclassHelloSpeakerimplementsIHello {
- publicvoidhello(String name) {
- System.out.println("Hello "+ name);
- }
- }
- packagecn.partner4java.proxy.staticproxy;
- /**
- * 代理对象,给被代理对象添加日志
- */
- publicclassHelloProxyimplementsIHello {
- privateIHello iHello;
- publicHelloProxy(IHello iHello) {
- super();
- this.iHello = iHello;
- }
- publicvoidhello(String name) {
- System.out.println("记录日志");
- iHello.hello(name);
- }
- }
- packagecn.partner4java.proxy.staticproxy;
- /**
- * 调用
- * @author partner4java
- *
- */
- publicclassProxyDemo {
- publicstaticvoidmain(String[] args) {
- IHello iHello =newHelloProxy(newHelloSpeaker());
- iHello.hello("long");
- }
- }
动态代理:
动态代理区别于静态带来实现的地方在于织入过程是在运行时动态进行的。自己实现一般实现java.lang.reflect.InvocationHandler接口。
例子:
- packagecn.partner4java.proxy.dynamicproxy;
- publicinterfaceIHello {
- publicvoidhello(String name);
- }
- packagecn.partner4java.proxy.dynamicproxy;
- /**
- * 被代理的对象,需要借助代理对象加入日志
- * @author partner4java
- *
- */
- publicclassHelloSpeakerimplementsIHello {
- publicvoidhello(String name) {
- System.out.println("Hello "+ name);
- }
- }
- packagecn.partner4java.proxy.dynamicproxy;
- importjava.lang.reflect.InvocationHandler;
- importjava.lang.reflect.Method;
- importjava.lang.reflect.Proxy;
- /**
- * 动态代理对象
- * @author partner4java
- *
- */
- publicclassLogHandlerimplementsInvocationHandler {
- privateObject delegate;
- publicObject bind(Object delegate){
- this.delegate = delegate;
- returnProxy.newProxyInstance(delegate.getClass().getClassLoader(),
- delegate.getClass().getInterfaces(),this);
- }
- /**
- * 代理对象,这里面还可以改变原有的方法
- */
- publicObject invoke(Object proxy, Method method, Object[] args)
- throwsThrowable {
- Object result =null;
- try{
- System.out.println("添加日志");
- result = method.invoke(delegate, args);
- }catch(Exception e) {
- e.printStackTrace();
- }
- returnnull;
- }
- }
- packagecn.partner4java.proxy.dynamicproxy;
- /**
- * 测试
- * @author partner4java
- *
- */
- publicclassProxyDemo {
- publicstaticvoidmain(String[] args) {
- LogHandler logHandler =newLogHandler();
- IHello iHello = (IHello) logHandler.bind(newHelloSpeaker());
- iHello.hello("long");
- }
- }
------------------------------------------------------------------
利用ProxyFactory连接CGLIB简单实现AOP:
加入包aopalliance.jar\cglib-nodep-2.1_3.jar
demo:
- packagecn.partner4java.proxy.proxyfactory;
- /**
- * 被代理的对象
- * @author partner4java
- *
- */
- publicclassMessageWriter {
- publicvoidwriteMessage(){
- System.out.println("world!");
- }
- }
- packagecn.partner4java.proxy.proxyfactory;
- importorg.aopalliance.intercept.MethodInterceptor;
- importorg.aopalliance.intercept.MethodInvocation;
- /**
- * 装饰者<br/>
- * MethodInterceptor接口是对方法调用连接点实现包围通知的AOP联盟标准接口
- * @author partner4java
- *
- */
- publicclassMessageDecoratorimplementsMethodInterceptor{
- publicObject invoke(MethodInvocation invocation)throwsThrowable {
- System.out.print("Hello ");
- Object retVal = invocation.proceed();
- returnretVal;
- }
- }
- packagecn.partner4java.proxy.proxyfactory;
- importorg.springframework.aop.framework.ProxyFactory;
- /**
- * 调用组装
- * 这里最重要的部分是我们使用ProxyFactory来创建一个目标对象代理,同时织入通知
- * @author partner4java
- *
- */
- publicclassHelloWorldWeaver {
- publicstaticvoidmain(String[] args) {
- //目标
- MessageWriter target =newMessageWriter();
- //create the proxy
- ProxyFactory proxyFactory =newProxyFactory();
- proxyFactory.addAdvice(newMessageDecorator());
- proxyFactory.setTarget(target);
- //获取返回被代理的目标
- MessageWriter proxy = (MessageWriter) proxyFactory.getProxy();
- target.writeMessage();
- System.out.println("---");
- proxy.writeMessage();
- //后台打印:
- //world!
- //---
- //World world!
- }
- }
------------------------------------------------------------------
代理
1.代理解决什么问题,为已存在的目标类的方法增加一些系统功能。如果采用工厂模式和配置文件进行管理,以后也很容易就可以去掉增加的功能。
2.静态代理类的工作原理,太多静态代理类,还有什么意思?jvm可以帮我们创建代理类,这就是动态代理类。
3.让jvm创建动态代理类,我们需要给它提供哪些信息?
让jvm帮我们创建一个类,我们需要为它提供哪些信息呢?a.有哪些方法,即告诉它实现哪些接口;b.产生的类必须有个妈妈,即类加载器对象;c.它生成的类中的方法的代码是怎样的,需我告诉它,我把我的代码写在一个约定好了接口的对象的方法中,把对象传给它,它调用我的方法,即相当于插入了我的代码。
4.写程序的步骤:
1). 快速演示动态代理的效果
- privatestaticvoidtest1() {
- Collection proxy = (Collection)Proxy.newProxyInstance(
- ProxyTest.class.getClassLoader(),//first parameter
- newClass[]{Collection.class} ,//second parameter
- newInvocationHandler(){//third parameter
- Vector target =newVector();
- @Override
- publicObject invoke(Object proxy, Method method,
- Object[] args)throwsThrowable {
- // TODO Auto-generated method stub
- System.out.println("begin "+ method.getName());
- Object retval = method.invoke(target, args);
- System.out.println("end"+ method.getName());
- returnretval;
- }
- }
- );
- //---
- System.out.println(proxy.getClass().getName());
- proxy.add("abc");
- proxy.add("xyz");
- System.out.println(proxy.size());
- //---
- }
2).可以接收外面传入的目标
- privatestaticvoidtest2() {
- Vector v =newVector();
- classMyInvocationHandlerimplementsInvocationHandler
- {
- Collection target =null;
- publicMyInvocationHandler(){}
- publicMyInvocationHandler(Collection target){this.target = target;}
- @Override
- publicObject invoke(Object proxy, Method method,
- Object[] args)throwsThrowable {
- // TODO Auto-generated method stub
- System.out.println("begin "+ method.getName());
- Object retval = method.invoke(target, args);
- System.out.println("end"+ method.getName());
- returnretval;
- }
- }
- Collection proxy1 = (Collection)Proxy.newProxyInstance(
- ProxyTest.class.getClassLoader(),
- newClass[]{Collection.class} ,
- newMyInvocationHandler(v));
- System.out.println(proxy1.getClass().getName());
- proxy1.add("abc");
- proxy1.add("xyz");
- System.out.println(proxy1.size());
- }
3).最优雅的方式,接收目标同时返回代理,让调用者更懒惰,更方便,调用者甚至不用接触任何代理的API。
- privatestaticvoidtest3() {
- Vector v =newVector();
- classMyInvocationHandlerimplementsInvocationHandler
- {
- Collection target =null;
- publicCollection bind(Collection target)
- {
- this.target = target;
- Collection proxy1 = (Collection)Proxy.newProxyInstance(
- ProxyTest.class.getClassLoader(),
- newClass[]{Collection.class} ,
- this);
- returnproxy1;
- }
- @Override
- publicObject invoke(Object proxy, Method method,
- Object[] args)throwsThrowable {
- // TODO Auto-generated method stub
- System.out.println("begin "+ method.getName());
- Object retval = method.invoke(target, args);
- System.out.println("end"+ method.getName());
- returnretval;
- }
- }
- MyInvocationHandler handler =newMyInvocationHandler();
- Collection proxy1 = handler.bind(v);
- System.out.println(proxy1.getClass().getName());
- proxy1.add("abc");
- proxy1.add("xyz");
- System.out.println(proxy1.size());
- }
一点小心得:静态方法中也可以定义内部类,只是内部类中不能方法外部类的成员变量。
- iterface Foo
- {
- doTest();
- }
- Class xxx = Proxy.getProxyClass(Foo.class.getClassLoader(),Class [] {Foo.class});
- Proxy方法自动生成一个类的字节码,这个自动生成的类实现了Foo接口(可以实现若干接口)。生成的类有Foo接口中的所有方法和一个如下形式的构造方法:
- Xxx
- {
- InvocationHandler handler;
- publicXxx(InvocationHandler handler)
- {
- this.handler = handler;
- }
- //生成的Foo接口中的方法的运行原理
- doTest()
- {
- handler.invoke(this,newMethod("doTest"),null)
- }
- }
- 创建代理类的实例对象的语法解释
- clsProxy.getConstructor(Class []{InvocationHandlre.class}).newInstance(xhandlder);
- Invocationhandler接口的实现示意:
- classMyInvocationHandler impments InvocationHandler
- {
- invoke(Object proxy,Method method,Object[] args)
- {
- log.info();
- Mehtod.invoke(yyy);
- }
- }