*****
1,动态代理
public interface UserDao { void save(); } public class UserDaoImpl implements UserDao { private String name; public void save() { System.out.println("save() is called, name: "+name); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
代理工厂
ProxyFactory.java
package com.maple.util; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.maple.dao.UserDao; import com.maple.dao.impl.UserDaoImpl; public class ProxyFactory implements InvocationHandler { private Object target; public Object createUserDao(Object target){ this.target=target; return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(proxy.getClass().getName()); Object result=null; UserDaoImpl userDao=(UserDaoImpl)this.target; if(userDao.getName()!=null){ result=method.invoke(userDao, args); }else{ System.out.println("the name is null"); } return result; } }
测试
@Test public void test() { ProxyFactory pf=new ProxyFactory(); UserDaoImpl u=new UserDaoImpl(); u.setName("maple"); UserDao userDao=(UserDao) pf.createUserDao(u); userDao.save(); }
输出
$Proxy5
save() is called, name: maple
2,cglib
UserDaoImpl2.java不实现接口
package com.maple.dao.impl; public class UserDaoImpl2{ private String name; public void save() throws InterruptedException { Thread.sleep(3000); System.out.println("save() is called, name: "+name); } public String getName() { return name; } public void setName(String name) { this.name = name; } public void raiseException(){ throw new RuntimeException("this is test"); } }
CglibFactory.java
package com.maple.util; import java.lang.reflect.Method; import com.maple.dao.impl.UserDaoImpl2; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibFactory implements MethodInterceptor { private Object target; public Object createUserDao(Object target){ this.target=target; Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { UserDaoImpl2 userDao=(UserDaoImpl2)target; System.out.println("begin"); if(userDao.getName()!=null){ method.invoke(target, args); }else{ System.out.println("the name is null"); } System.out.println("end"); return null; } }
测试代码:
@Test public void test2() throws InterruptedException{ CglibFactory cf=new CglibFactory(); UserDaoImpl2 temp=new UserDaoImpl2(); UserDaoImpl2 userDao=(UserDaoImpl2)cf.createUserDao(temp); userDao.save(); temp.setName("aa"); userDao=(UserDaoImpl2)cf.createUserDao(temp); userDao.save(); }
结果:
begin
the name is null
end
begin
save() is called, name: aa
end
3,spring综合了动态代理和cglib
UserDaoImpl,java,UserDaoImpl2.java同上
定义一个切面类MyInterceptor.java
package com.maple.util; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyInterceptor { //返回值任意,该包下面的所有类的所有方法,方法的参数个数任意 @Pointcut("execution ( * com.maple.dao.impl.*.*(..))") public void anyMethod(){} @Before("anyMethod()")//执行符合切点的方法前执行 public void before(){ System.out.println("before()"); } @After("anyMethod()") public void after(){ System.out.println("after()"); } @Around("anyMethod()") public void Around(ProceedingJoinPoint pjp) throws Throwable{ long start=System.currentTimeMillis(); System.out.println("begin around()"); pjp.proceed(); System.out.println("end around()"); long end=System.currentTimeMillis(); System.out.println("the time is "+(end-start)); } @Before("anyMethod() && args(name)") public void before(String name){ System.out.println("before(name): the name is:"+name); } @AfterReturning(pointcut="anyMethod()",returning="result") public void afterReturning(String result){ System.out.println("the result is "+result); } @AfterThrowing(pointcut="anyMethod()",throwing="e") public void afterThrowing(Exception e){ e.printStackTrace(); } }
测试
@Test public void test3() throws InterruptedException{ ApplicationContext context=new ClassPathXmlApplicationContext("/beans.xml"); UserDao userDao=(UserDao) context.getBean("userDaoImpl"); //userDao.save(); UserDaoImpl2 userDao2=(UserDaoImpl2) context.getBean("userDaoImpl2"); //userDao2.save(); userDao2.setName("hhh"); //userDao2.raiseException(); //System.out.println(userDao2.getName()); }
在spring的配置文件beans.xml中
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <aop:aspectj-autoproxy/> <!-- spring打开aop功能 --> <bean id="userDaoImpl" class="com.maple.dao.impl.UserDaoImpl"/> <bean id="userDaoImpl2" class="com.maple.dao.impl.UserDaoImpl2"/> <bean id="myInterceptor444" class="com.maple.util.MyInterceptor"/> </beans>
结果:
before()
before(name): the name is:hhh
begin around()
after()
end around()
the time is 0
the result is null
如果留下userDao2.save(),其他调用注释,则结果如下:
before()
begin around()
save() is called, name: null
after()
end around()
the time is 1
the result is null
注:1,在配置文件中如果没有对切面类的bean的定义,则不会执行切面类中的那些方法如before(),??
2,2个before方法都执行了,然后around开始,执行方法,执行after,around结束,执行afterReturning()
*****