两种类型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:
- package cn.partner4java.proxy.staticproxy;
- /**
- * 静态代理,统一接口
- * @author partner4java
- *
- */
- public interface IHello {
- /**
- * 可以带来的统一方法
- * @param name
- */
- public void hello(String name);
- }
- package cn.partner4java.proxy.staticproxy;
- /**
- * 被代理的对象,需要借助代理对象加入日志
- * @author partner4java
- *
- */
- public class HelloSpeaker implements IHello {
- public void hello(String name) {
- System.out.println("Hello " + name);
- }
- }
- package cn.partner4java.proxy.staticproxy;
- /**
- * 代理对象,给被代理对象添加日志
- */
- public class HelloProxy implements IHello {
- private IHello iHello;
- public HelloProxy(IHello iHello) {
- super();
- this.iHello = iHello;
- }
- public void hello(String name) {
- System.out.println("记录日志");
- iHello.hello(name);
- }
- }
- package cn.partner4java.proxy.staticproxy;
- /**
- * 调用
- * @author partner4java
- *
- */
- public class ProxyDemo {
- public static void main(String[] args) {
- IHello iHello = new HelloProxy(new HelloSpeaker());
- iHello.hello("long");
- }
- }
动态代理:
动态代理区别于静态带来实现的地方在于织入过程是在运行时动态进行的。自己实现一般实现java.lang.reflect.InvocationHandler接口。
例子:
- package cn.partner4java.proxy.dynamicproxy;
- public interface IHello {
- public void hello(String name);
- }
- package cn.partner4java.proxy.dynamicproxy;
- /**
- * 被代理的对象,需要借助代理对象加入日志
- * @author partner4java
- *
- */
- public class HelloSpeaker implements IHello {
- public void hello(String name) {
- System.out.println("Hello " + name);
- }
- }
- package cn.partner4java.proxy.dynamicproxy;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- /**
- * 动态代理对象
- * @author partner4java
- *
- */
- public class LogHandler implements InvocationHandler {
- private Object delegate;
- public Object bind(Object delegate){
- this.delegate = delegate;
- return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
- delegate.getClass().getInterfaces(), this);
- }
- /**
- * 代理对象,这里面还可以改变原有的方法
- */
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- Object result = null;
- try {
- System.out.println("添加日志");
- result = method.invoke(delegate, args);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- }
- package cn.partner4java.proxy.dynamicproxy;
- /**
- * 测试
- * @author partner4java
- *
- */
- public class ProxyDemo {
- public static void main(String[] args) {
- LogHandler logHandler = new LogHandler();
- IHello iHello = (IHello) logHandler.bind(new HelloSpeaker());
- iHello.hello("long");
- }
- }
------------------------------------------------------------------
利用ProxyFactory连接CGLIB简单实现AOP:
加入包aopalliance.jar\cglib-nodep-2.1_3.jar
demo:
- package cn.partner4java.proxy.proxyfactory;
- /**
- * 被代理的对象
- * @author partner4java
- *
- */
- public class MessageWriter {
- public void writeMessage(){
- System.out.println("world!");
- }
- }
- package cn.partner4java.proxy.proxyfactory;
- import org.aopalliance.intercept.MethodInterceptor;
- import org.aopalliance.intercept.MethodInvocation;
- /**
- * 装饰者<br/>
- * MethodInterceptor接口是对方法调用连接点实现包围通知的AOP联盟标准接口
- * @author partner4java
- *
- */
- public class MessageDecorator implements MethodInterceptor{
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.print("Hello ");
- Object retVal = invocation.proceed();
- return retVal;
- }
- }
- package cn.partner4java.proxy.proxyfactory;
- import org.springframework.aop.framework.ProxyFactory;
- /**
- * 调用组装
- * 这里最重要的部分是我们使用ProxyFactory来创建一个目标对象代理,同时织入通知
- * @author partner4java
- *
- */
- public class HelloWorldWeaver {
- public static void main(String[] args) {
- //目标
- MessageWriter target = new MessageWriter();
- //create the proxy
- ProxyFactory proxyFactory = new ProxyFactory();
- proxyFactory.addAdvice(new MessageDecorator());
- 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). 快速演示动态代理的效果
- private static void test1() {
- Collection proxy = (Collection)Proxy.newProxyInstance(
- ProxyTest.class.getClassLoader(),//first parameter
- new Class[]{Collection.class} , //second parameter
- new InvocationHandler(){ //third parameter
- Vector target = new Vector();
- @Override
- public Object invoke(Object proxy, Method method,
- Object[] args) throws Throwable {
- // TODO Auto-generated method stub
- System.out.println("begin " + method.getName());
- Object retval = method.invoke(target, args);
- System.out.println("end" + method.getName());
- return retval;
- }
- }
- );
- //---
- System.out.println(proxy.getClass().getName());
- proxy.add("abc");
- proxy.add("xyz");
- System.out.println(proxy.size());
- //---
- }
2).可以接收外面传入的目标
- private static void test2() {
- Vector v = new Vector();
- class MyInvocationHandler implements InvocationHandler
- {
- Collection target = null;
- public MyInvocationHandler(){}
- public MyInvocationHandler(Collection target){this.target = target;}
- @Override
- public Object invoke(Object proxy, Method method,
- Object[] args) throws Throwable {
- // TODO Auto-generated method stub
- System.out.println("begin " + method.getName());
- Object retval = method.invoke(target, args);
- System.out.println("end" + method.getName());
- return retval;
- }
- }
- Collection proxy1 = (Collection)Proxy.newProxyInstance(
- ProxyTest.class.getClassLoader(),
- new Class[]{Collection.class} ,
- new MyInvocationHandler(v));
- System.out.println(proxy1.getClass().getName());
- proxy1.add("abc");
- proxy1.add("xyz");
- System.out.println(proxy1.size());
- }
3).最优雅的方式,接收目标同时返回代理,让调用者更懒惰,更方便,调用者甚至不用接触任何代理的API。
- private static void test3() {
- Vector v = new Vector();
- class MyInvocationHandler implements InvocationHandler
- {
- Collection target = null;
- public Collection bind(Collection target)
- {
- this.target = target;
- Collection proxy1 = (Collection)Proxy.newProxyInstance(
- ProxyTest.class.getClassLoader(),
- new Class[]{Collection.class} ,
- this);
- return proxy1;
- }
- @Override
- public Object invoke(Object proxy, Method method,
- Object[] args) throws Throwable {
- // TODO Auto-generated method stub
- System.out.println("begin " + method.getName());
- Object retval = method.invoke(target, args);
- System.out.println("end" + method.getName());
- return retval;
- }
- }
- MyInvocationHandler handler = new MyInvocationHandler();
- 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;
- public Xxx(InvocationHandler handler)
- {
- this.handler = handler;
- }
- //生成的Foo接口中的方法的运行原理
- doTest()
- {
- handler.invoke(this,new Method("doTest"),null)
- }
- }
- 创建代理类的实例对象的语法解释
- clsProxy.getConstructor(Class []{InvocationHandlre.class}).newInstance(xhandlder);
- Invocationhandler接口的实现示意:
- class MyInvocationHandler impments InvocationHandler
- {
- invoke(Object proxy,Method method,Object[] args)
- {
- log.info();
- Mehtod.invoke(yyy);
- }
- }