Proxy 就是代理,意思就是 你不用去做,别人代替你去处理
先来个静态代理
public interface Hello { void say(String name); } 被代理类 public class HelloImpl implements Hello { @Override public void say(String name) { System.out.println("Hello! " + name); } } 代理类 public class HelloProxy implements Hello { private HelloImpl helloImpl; public HelloProxy() { helloImpl = new HelloImpl(); } @Override public void say(String name) { before(); helloImpl.say(name); after(); } private void before() { System.out.println("Before"); } private void after() { System.out.println("After"); } }
再来个动态代理
public class DynamicProxy implements InvocationHandler { private Object target; public DynamicProxy(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object result = method.invoke(target, args); after(); return result; } @SuppressWarnings("unchecked") public <T> T getProxy() { return (T) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this ); } } public static void main(String[] args) { DynamicProxy dynamicProxy = new DynamicProxy(new HelloImpl()); Hello helloProxy = dynamicProxy.getProxy(); helloProxy.say("Jack"); }
但是 只能代理有借口的类
使用 CGLib 来进行代理
public class CGLibProxy implements MethodInterceptor { private static CGLibProxy instance = new CGLibProxy(); private CGLibProxy() { } public static CGLibProxy getInstance() { return instance; } public <T> T getProxy(Class<T> cls) { return (T) Enhancer.create(cls, this); } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { before(); Object result = proxy.invokeSuper(obj, args); after(); return result; } ... } public class Client { public static void main(String[] args) { Greeting greeting = CGLibDynamicProxy.getInstance().getProxy(GreetingImpl.class); greeting.sayHello("Jack"); } }
Proxy 感觉好像 Decorator 啊
代理模式(Proxy 模式)可理解为:我想做,但不能做,我需要有一个能干的人来帮我做。 需要一个能人
装饰器模式(Decorator 模式)可理解为:我想做,但不能做,我需要有各类特长的人来帮我做,但我有时只需要一个人,有时又需要很多人 需要一个团队
public interface Greeting { void sayHello(String name); } public class GreetingImpl implements Greeting { @Override public void sayHello(String name) { System.out.println("Hello! " + name); } } public class GreetingProxy implements Greeting { private GreetingImpl greetingImpl; public GreetingProxy(GreetingImpl greetingImpl) { this.greetingImpl = greetingImpl; } @Override public void sayHello(String name) { before(); greetingImpl.sayHello(name); } private void before() { System.out.println("Before"); } } //开闭原则”对扩展开放,对修改封闭”。没错,我们确实是提供了 GreetingProxy 类来扩展 GreetingImpl 的功能,而并非去修改 GreetingImpl 原有的代码。
如果需要做的操作越来越多,一下子是日志记录,一下子是事务控制,还有权限控制,还有数据缓存。把所有的功能都放在这个 Proxy 类中是不明智的,同时这也违反了“开闭原则”
来看看装饰器模式
//干净的装饰器 public abstract class GreetingDecorator implements 接口类{ private Greeting greeting; public GreetingDecorator(Greeting greeting) { this.greeting = greeting; } @Override public void sayHello(String name) { greeting.sayHello(name); } } //日志功能 public class GreetingBefore extends GreetingDecorator { public GreetingBefore(Greeting greeting) { super(greeting); } @Override public void sayHello(String name) { before(); super.sayHello(name); } private void before() { System.out.println("Before"); } } //其他功能 public class GreetingAfter extends GreetingDecorator { public GreetingAfter(Greeting greeting) { super(greeting); } @Override public void sayHello(String name) { super.sayHello(name); after(); } private void after() { System.out.println("After"); } } //使用 public class ClientDecorator { public static void main(String[] args) { Greeting greeting = new GreetingAfter(new GreetingBefore(new GreetingImpl())); greeting.sayHello("Jack"); } }
这就使用了装饰器模式
InputStream input = new DataInputStream(new BufferedInputStream(new FileInputStream("C:/test.exe")));
Spring AOP:前置增强、后置增强、环绕增强 抛出增强(ThrowsAdvice )
前,后置增强 public class GreetingBeforeAndAfterAdvice implements MethodBeforeAdvice, AfterReturningAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("Before"); } @Override public void afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable { System.out.println("After"); } } public class Client { public static void main(String[] args) { ProxyFactory proxyFactory = new ProxyFactory(); // 创建代理工厂 proxyFactory.setTarget(new GreetingImpl()); // 射入目标类对象 proxyFactory.addAdvice(new GreetingBeforeAdvice()); // 添加前置增强 proxyFactory.addAdvice(new GreetingAfterAdvice()); // 添加后置增强 Greeting greeting = (Greeting) proxyFactory.getProxy(); // 从代理工厂中获取代理 greeting.sayHello("Jack"); // 调用代理的方法 } } 也可以实现MethodInterceptor 实现环绕增强
<!-- 扫描指定包(将 @Component 注解的类自动定义为 Spring Bean) --> <context:component-scan base-package="aop.demo"/> <!-- 配置一个代理 --> <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces" value="aop.Greeting"/> <!-- 需要代理的接口 --> <property name="target" ref="greetingImpl"/> <!-- 接口实现类 --> <property name="interceptorNames"> <!-- 拦截器名称(也就是增强类名称,Spring Bean 的 id) --> <list> <value>greetingAroundAdvice</value> </list> </property> </bean> </beans> 加上@Component public class Client { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml"); // 获取 Spring Context Greeting greeting = (Greeting) context.getBean("greetingProxy"); // 从 Context 中根据 id 获取 Bean 对象(其实就是一个代理) greeting.sayHello("Jack"); // 调用代理的方法 } }
引入增强(如果某个类实现了 A 接口,但没有实现 B 接口,那么该类可以调用 B 接口的方法吗?)
新定义B接口 public interface Apology { void saySorry(String name); } @Component public class GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology { @Override public Object invoke(MethodInvocation invocation) throws Throwable { return super.invoke(invocation); } @Override public void saySorry(String name) { System.out.println("Sorry! " + name); } } <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces" value="aop.demo.Apology"/> <!-- 需要动态实现的接口 --> <property name="target" ref="greetingImpl"/> <!-- 目标类 --> <property name="interceptorNames" value="greetingIntroAdvice"/> <!-- 引入增强 --> <property name="proxyTargetClass" value="true"/> <!-- 代理目标类(默认为 false,代理接口) --> </bean> public class Client { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml"); GreetingImpl greetingImpl = (GreetingImpl) context.getBean("greetingProxy"); // 注意:转型为目标类,而并非它的 Greeting 接口 greetingImpl.sayHello("Jack"); Apology apology = (Apology) greetingImpl; // 将目标类强制向上转型为 Apology 接口(这是引入增强给我们带来的特性,也就是“接口动态实现”功能) apology.saySorry("Jack"); } }
前面全是拦截整个类,有时候老子不需要拦不漂亮的,与是就想到了spring 的切面(Advisor)
将拦截匹配条件(Pointcut)与增强(Advice)结合在一起
@Component public class GreetingImpl implements Greeting { @Override public void sayHello(String name) { System.out.println("Hello! " + name); } public void goodMorning(String name) { System.out.println("Good Morning! " + name); } public void goodNight(String name) { System.out.println("Good Night! " + name); } } <beans ..."> <context:component-scan base-package="aop.demo"/> <!-- 配置一个切面 --> <bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice" ref="greetingAroundAdvice"/> <!-- 增强 --> <property name="pattern" value="aop.demo.GreetingImpl.good.*"/> <!-- 切点(正则表达式) -->匹配 aop.demo.GreetingImpl 类中以 good 开头的方法” </bean> <!-- 配置一个代理 --> <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="greetingImpl"/> <!-- 目标类 --> <property name="interceptorNames" value="greetingAdvisor"/> <!-- 切面 --> <property name="proxyTargetClass" value="true"/> <!-- 代理目标类 --> </bean> </beans> DefaultPointcutAdvisor:默认切面(可扩展它来自定义切面) NameMatchMethodPointcutAdvisor:根据方法名称进行匹配的切面 StaticMethodMatcherPointcutAdvisor:用于匹配静态方法的切面
让用户去配置一个或少数几个代理,似乎还可以接受,但随着项目的扩大,代理配置就会越来越多,配置的重复劳动就多了,麻烦不说,还很容易出错。能否让 Spring 框架为我们自动生成代理
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames" value="*Impl"/> <!-- 只为后缀是“Impl”的 Bean 生成代理 --> <property name="interceptorNames" value="greetingAroundAdvice"/> <!-- 增强 --> <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化 --> </bean> 以上使用 BeanNameAutoProxyCreator 只为后缀为“Impl”的 Bean 生成代理。需要注意的是,这个地方我们不能定义代理接口,也就是 interfaces 属性,因为我们根本就不知道这些 Bean 到底实现了多少接口。此时不能代理接口,而只能代理类。所以这里提供了一个新的配置项,它就是 optimize。若为 true 时,则可对代理生成策略进行优化(默认是 false 的)。也就是说,如果该类有接口,就代理接口(使用 JDK 动态代理);如果没有接口,就代理类(使用 CGLib 动态代理)。而并非像之前使用的 proxyTargetClass 属性那样,强制代理类,而不考虑代理接口的方式 既然 CGLib 可以代理任何的类了,那为什么还要用 JDK 的动态代理呢?肯定您会这样问。 根据多年来实际项目经验得知:CGLib 创建代理的速度比较慢,但创建代理后运行的速度却非常快,而 JDK 动态代理正好相反。如果在运行的时候不断地用 CGLib 去创建代理,系统的性能会大打折扣,所以建议一般在系统初始化的时候用 CGLib 去创建代理,并放入 Spring 的 ApplicationContext 中以备后用。 以上这个例子只能匹配目标类,而不能进一步匹配其中指定的方法,要匹配方法,就要考虑使用切面与切点了。
上面配置实在是累啊,想拦截指定注解的方法,我们就必须扩展 DefaultPointcutAdvisor 类,自定义一个切面类,然后在 Spring 配置文件中进行切面配置
Spring + AspectJ
@Aspect @Component public class GreetingAspect { @Around("execution(* aop.demo.GreetingImpl.*(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable { before(); Object result = pjp.proceed(); after(); return result; } private void before() { System.out.println("Before"); } private void after() { System.out.println("After"); } } execution():表示拦截方法,括号中可定义需要匹配的规则。 第一个“*”:表示方法的返回值是任意的。 第二个“*”:表示匹配该类中所有的方法。 (..):表示方法的参数是任意的。 <context:component-scan base-package="aop.demo"/> <aop:aspectj-autoproxy proxy-target-class="true"/> 默认为false(只能代理接口),为true时,代理目标类(使用CGLib动态代理)
Spring 与 AspectJ 结合的威力远远不止这些,我们来点时尚的吧,拦截指定注解的方法怎么样?
//先定义一个注解,标注在方法上,运行时生效 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Tag { } //只需将前面的 Aspect 类的切点表达式稍作改动: @Aspect @Component public class GreetingAspect { @Around("@annotation(aop.demo.Tag)") // 拦截有这个注解的 public Object around(ProceedingJoinPoint pjp) throws Throwable { ... } ... } //被拦截的,将 @Tag 注解定义在您想要拦截的方法上 @Component public class GreetingImpl implements Greeting { @Tag @Override public void sayHello(String name) { System.out.println("Hello! " + name); } } @Before:前置增强 @After:后置增强 @Around:环绕增强 @AfterThrowing:抛出增强 @DeclareParents:引入增强
实现下牛B的引入增强
@Aspect @Component public class GreetingAspect { @DeclareParents(value = "aop.demo.GreetingImpl", defaultImpl = ApologyImpl.class) private Apology apology; } value:目标类 defaultImpl:引入接口的默认实现类 public class ApologyImpl implements Apology { @Override public void saySorry(String name) { System.out.println("Sorry! " + name); } } public class Client { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml"); Greeting greeting = (Greeting) context.getBean("greetingImpl"); greeting.sayHello("Jack"); Apology apology = (Apology) greeting; // 强制转型为 Apology 接口 apology.saySorry("Jack"); } } 从 Spring ApplicationContext 中获取 greetingImpl 对象(其实是个代理对象),可转型为自己静态实现的接口 Greeting,也可转型为自己动态实现的接口 Apology,切换起来非常方便
对于jdk1.4以下没有注解的只能通过配置来使用的
<beans ..."> <bean id="greetingImpl" class="aop.demo.GreetingImpl"/> <bean id="greetingAspect" class="aop.demo.GreetingAspect"/> <aop:config> <aop:aspect ref="greetingAspect"> <aop:around method="around" pointcut="execution(* aop.demo.GreetingImpl.*(..))"/> </aop:aspect> </aop:config> </beans>
spring
AOP原理
实现轻量级AOP
@Bean @Aspect(pkg = "com.smart.sample.action", cls = "ProductAction") public class ProductActionAspect extends BaseAspect { @Override protected Object advice(Pointcut pointcut, Object proxy, Object[] args) { long begin = System.currentTimeMillis(); Object result = pointcut.invoke(proxy, args); System.out.println("Time: " + (System.currentTimeMillis() - begin) + "ms"); return result; } } //使用了Cglib public abstract class BaseAspect implements MethodInterceptor { @SuppressWarnings("unchecked") public <T> T getProxy(Class<T> cls) { return (T) Enhancer.create(cls, this); } @Override public Object intercept(Object proxy, Method methodTarget, Object[] args, MethodProxy methodProxy) throws Throwable { return advice(new Pointcut(methodTarget, methodProxy), proxy, args); } protected abstract Object advice(Pointcut pointcut, Object proxy, Object[] args); protected class Pointcut { private Method methodTarget; private MethodProxy methodProxy; public Pointcut(Method methodTarget, MethodProxy methodProxy) { this.methodTarget = methodTarget; this.methodProxy = methodProxy; } public Method getMethodTarget() { return methodTarget; } public MethodProxy getMethodProxy() { return methodProxy; } public Object invoke(Object proxy, Object[] args) { Object result = null; try { result = methodProxy.invokeSuper(proxy, args); } catch (Throwable e) { e.printStackTrace(); } return result; } } }
public class AOPHelper { static { try { // 获取带有 @Aspect 注解的类(切面类) List<Class<?>> aspectClassList = ClassHelper.getClassListByAnnotation(Aspect.class); // 遍历所有切面类 for (Class<?> aspectClass : aspectClassList) { // 获取 @Aspect 注解中的属性值 Aspect aspect = aspectClass.getAnnotation(Aspect.class); String pkg = aspect.pkg(); // 包名 String cls = aspect.cls(); // 类名 // 初始化目标类列表 List<Class<?>> targetClassList = new ArrayList<Class<?>>(); if (StringUtil.isNotEmpty(pkg) && StringUtil.isNotEmpty(cls)) { // 如果包名与类名均不为空,则添加指定类 targetClassList.add(Class.forName(pkg + "." + cls)); } else { // 否则(包名不为空)添加该包名下所有类 targetClassList.addAll(ClassHelper.getClassListByPackage(pkg)); } // 遍历目标类列表 if (CollectionUtil.isNotEmpty(targetClassList)) { // 创建父切面类 BaseAspect baseAspect = (BaseAspect) aspectClass.newInstance(); for (Class<?> targetClass : targetClassList) { // 获取目标实例 Object targetInstance = BeanHelper.getBean(targetClass); // 创建代理实例 Object proxyInstance = baseAspect.getProxy(targetClass); // 复制目标实例中的字段到代理实例中 for (Field field : targetClass.getDeclaredFields()) { field.setAccessible(true); // 可操作私有字段 field.set(proxyInstance, field.get(targetInstance)); } // 用代理实例覆盖目标实例 BeanHelper.getBeanMap().put(targetClass, proxyInstance); } } } } catch (Exception e) { e.printStackTrace(); } } }
想要拦截特定方法
@Override protected Object advice(Pointcut pointcut, Object proxy, Object[] args) { Object result; Method method = pointcut.getMethodTarget(); if (method.getName().equals("getProducts")) { long begin = System.currentTimeMillis(); result = pointcut.invoke(proxy, args); System.out.println("Time: " + (System.currentTimeMillis() - begin) + "ms"); } else { result = pointcut.invoke(proxy, args); } return result; }
//去掉pointcut public abstract class BaseAspect implements MethodInterceptor { @SuppressWarnings("unchecked") public <T> T getProxy(Class<T> cls) { return (T) Enhancer.create(cls, this); } @Override public Object intercept(Object proxy, Method methodTarget, Object[] args, MethodProxy methodProxy) throws Throwable { Object result = null; if (filter(methodTarget, args)) { before(methodTarget, args); try { result = methodProxy.invokeSuper(proxy, args); } catch (Exception e) { e.printStackTrace(); error(methodTarget, args, e); } after(methodTarget, args); } else { result = methodProxy.invokeSuper(proxy, args); } return result; } protected boolean filter(Method method, Object[] args) { return true; } protected void before(Method method, Object[] args) { } protected void after(Method method, Object[] args) { } protected void error(Method method, Object[] args, Exception e) { } } @Bean @Aspect(pkg = "com.smart.sample.action", cls = "ProductAction") public class ProductActionAspect extends BaseAspect { private long begin; @Override protected boolean filter(Method method, Object[] args) { return method.getName().equals("getProducts"); } @Override protected void before(Method method, Object[] args) { begin = System.currentTimeMillis(); } @Override protected void after(Method method, Object[] args) { System.out.println("Time: " + (System.currentTimeMillis() - begin) + "ms"); } @Override protected void error(Method method, Object[] args, Exception e) { System.out.println("Error: " + e.getMessage()); } }
事务管理实现原理 (事务隔离级别、事务传播行为、事务超时等搞不动)
@Bean public class ProductServiceImpl extends BaseService implements ProductService { ... @Override @Transaction public boolean createProduct(Map<String, Object> productFieldMap) { String sql = SQLHelper.getSQL("insert.product"); Object[] params = { productFieldMap.get("productTypeId"), productFieldMap.get("productName"), productFieldMap.get("productCode"), productFieldMap.get("price"), productFieldMap.get("description") }; int rows = DBHelper.update(sql, params); if (true) { throw new RuntimeException("Insert log failure!"); // 故意抛出异常,让事务回滚 } return rows == 1; } } public class DBHelper { private static final BasicDataSource ds = new BasicDataSource(); private static final QueryRunner runner = new QueryRunner(ds); // 定义一个局部线程变量(使每个线程都拥有自己的连接) private static ThreadLocal<Connection> connContainer = new ThreadLocal<Connection>(); static { System.out.println("Init DBHelper..."); // 初始化数据源 ds.setDriverClassName(ConfigHelper.getStringProperty("jdbc.driver")); ds.setUrl(ConfigHelper.getStringProperty("jdbc.url")); ds.setUsername(ConfigHelper.getStringProperty("jdbc.username")); ds.setPassword(ConfigHelper.getStringProperty("jdbc.password")); ds.setMaxActive(ConfigHelper.getNumberProperty("jdbc.max.active")); ds.setMaxIdle(ConfigHelper.getNumberProperty("jdbc.max.idle")); } // 获取数据源 public static DataSource getDataSource() { return ds; } // 开启事务 public static void beginTransaction() { Connection conn = connContainer.get(); if (conn == null) { try { conn = ds.getConnection(); conn.setAutoCommit(false); } catch (Exception e) { e.printStackTrace(); } finally { connContainer.set(conn); } } } // 提交事务 public static void commitTransaction() { Connection conn = connContainer.get(); if (conn != null) { try { conn.commit(); conn.close(); } catch (Exception e) { e.printStackTrace(); } finally { connContainer.remove(); } } } // 回滚事务 public static void rollbackTransaction() { Connection conn = connContainer.get(); if (conn != null) { try { conn.rollback(); conn.close(); } catch (Exception e) { e.printStackTrace(); } finally { connContainer.remove(); } } } ... // 执行更新(包括 UPDATE、INSERT、DELETE) public static int update(String sql, Object... params) { // 若当前线程中存在连接,则传入(用于事务处理),否则将从数据源中获取连接 Connection conn = connContainer.get(); return DBUtil.update(runner, conn, sql, params); } } public class DBUtil { ... // 更新(包括 UPDATE、INSERT、DELETE,返回受影响的行数) public static int update(QueryRunner runner, Connection conn, String sql, Object... params) { int result = 0; try { //对传进来的conn进行判断。为空,就DataSource 中自动获取,无需考虑事务问题,是自动提交的 //若不为空,就是处理过的conn,设置不自动提交,包含事务 if (conn != null) { result = runner.update(conn, sql, params); } else { result = runner.update(sql, params); } } catch (SQLException e) { e.printStackTrace(); } return result; } } //通过动态代理实现事务的开启与关闭 public class TransactionProxy implements MethodInterceptor { private static TransactionProxy instance = new TransactionProxy(); private TransactionProxy() { } public static TransactionProxy getInstance() { return instance; } @SuppressWarnings("unchecked") public <T> T getProxy(Class<T> cls) { return (T) Enhancer.create(cls, this); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object result; if (method.isAnnotationPresent(Transaction.class)) { try { // 开启事务 DBHelper.beginTransaction(); // 执行操作 method.setAccessible(true); result = proxy.invokeSuper(obj, args); // 提交事务 DBHelper.commitTransaction(); } catch (Exception e) { // 回滚事务 DBHelper.rollbackTransaction(); e.printStackTrace(); throw new RuntimeException(); } } else { result = proxy.invokeSuper(obj, args); } return result; } } 负责IOC的容器 public class BeanHelper { // Bean 类 => Bean 实例 private static final Map<Class<?>, Object> beanMap = new HashMap<Class<?>, Object>(); static { System.out.println("Init BeanHelper..."); try { // 获取并遍历所有的 Bean(带有 @Bean 注解的类) List<Class<?>> beanClassList = ClassHelper.getClassListByAnnotation(Bean.class); for (Class<?> beanClass : beanClassList) { // 创建 Bean 实例 Object beanInstance; if (BaseService.class.isAssignableFrom(beanClass)) { // 若为 Service 类,则获取动态代理实例(可以使用 CGLib 动态代理,不能使用 JDK 动态代理,因为初始化 Bean 字段时会报错) beanInstance = TransactionProxy.getInstance().getProxy(beanClass); } else { // 否则通过反射创建实例 beanInstance = beanClass.newInstance(); } // 将 Bean 实例放入 Bean Map 中(键为 Bean 类,值为 Bean 实例) beanMap.put(beanClass, beanInstance); } // 遍历 Bean Map for (Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()) { ... } } catch (Exception e) { e.printStackTrace(); } } ... }
当我CgLib 不能嵌套增强 , 像 装饰器那种那样
于是想到了借鉴 Servlet 的 Filter Chain 的设计模式,它是“责任链模式”的一种变体,在 JavaEE 设计模式中命名为“拦截过滤器模式”
public interface Proxy { void doProxy(ProxyChain proxyChain); } public class ProxyChain { private List<Proxy> proxyList; private int currentProxyIndex = 0; private Class<?> targetClass; private Object targetObject; private Method targetMethod; private Object[] methodParams; private MethodProxy methodProxy; private Object methodResult; public ProxyChain(Class<?> targetClass, Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy, List<Proxy> proxyList) { this.targetClass = targetClass; this.targetObject = targetObject; this.targetMethod = targetMethod; this.methodParams = methodParams; this.methodProxy = methodProxy; this.proxyList = proxyList; } public Class<?> getTargetClass() { return targetClass; } public Object getTargetObject() { return targetObject; } public Method getTargetMethod() { return targetMethod; } public Object[] getMethodParams() { return methodParams; } public MethodProxy getMethodProxy() { return methodProxy; } public Object getMethodResult() { return methodResult; } public void doProxyChain() { if (currentProxyIndex < proxyList.size()) { proxyList.get(currentProxyIndex++).doProxy(this); } else { try { methodResult = methodProxy.invokeSuper(targetObject, methodParams); } catch (Throwable throwable) { throw new RuntimeException(throwable); } } } } public class ProxyManager { private Class<?> targetClass; private List<Proxy> proxyList; public ProxyManager(Class<?> targetClass, List<Proxy> proxyList) { this.targetClass = targetClass; this.proxyList = proxyList; } private static ProxyManager instance = null; private ProxyManager() { } public static ProxyManager getInstance() { if (instance == null) { instance = new ProxyManager(); } return instance; } @SuppressWarnings("unchecked") public <T> T createProxy() { return (T) Enhancer.create(targetClass, new MethodInterceptor() { @Override public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable { ProxyChain proxyChain = new ProxyChain(targetClass, target, method, args, proxy, proxyList); proxyChain.doProxyChain(); return proxyChain.getMethodResult(); } }); } } //我们的目标不是为了实现 Proxy,而是为了实现 AOP。为了实现 AOP,我采用了“模板方法模式”, 弄一个 AbstractProxy 抽象类,让它去实现 Proxy 接口,并在其中定义方法调用模板,在需要横向拦截的地方,定义一些“钩子方法” public abstract class AbstractProxy implements Proxy { @Override public final void doProxy(ProxyChain proxyChain) { Class<?> cls = proxyChain.getTargetClass(); Method method = proxyChain.getTargetMethod(); Object[] params = proxyChain.getMethodParams(); begin(); try { if (filter(cls, method, params)) { before(cls, method, params); proxyChain.doProxyChain(); after(cls, method, params); } else { proxyChain.doProxyChain(); } } catch (Throwable e) { error(cls, method, params, e); } finally { end(); } } public void begin() { } public boolean filter(Class<?> cls, Method method, Object[] params) { return true; } public void before(Class<?> cls, Method method, Object[] params) { } public void after(Class<?> cls, Method method, Object[] params) { } public void error(Class<?> cls, Method method, Object[] params, Throwable e) { } public void end() { } } 利用 AbstractProxy 重新实现 BeforeProxy 与 AfterProxy public class BeforeProxy extends AbstractProxy { @Override public void before(Class<?> cls, Method method, Object[] params) { System.out.println("Before"); } } public class AfterProxy extends AbstractProxy { @Override public void after(Class<?> cls, Method method, Object[] params) { System.out.println("After"); } } //Client 类 //先构造一个空的 List<Proxy> proxyList,然后往里面依次放入需要增强的 Proxy 类, //随后使用 ProxyManager 去创建代理实例,最后调用代理实例的方法,完成对目标方法的横切 public class Client { public static void main(String[] args) { List<Proxy> proxyList = new ArrayList<Proxy>(); proxyList.add(new BeforeProxy()); proxyList.add(new AfterProxy()); ProxyManager proxyManager = new ProxyManager(GreetingImpl.class, proxyList); GreetingImpl greetingProxy = proxyManager.createProxy(); greetingProxy.sayHello("Jack"); } }
在springboot中的运用 在加入Spring-data-jpa 发现已被引入了
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
可以加上这个注解@EnableAspectJAutoProxy
@Aspect
@Component
曾经觉得AOP这个概念很神奇,认真研究过之后发现现实实现总有很多限制,越来越觉得这个不就是管道事件的另一个说法吗?区别就是事件得预先定义,AOP可以后续注入,但总觉得后续注入这个需求是程序员自己偷懒的做法,不是业务模型架构该有的设计,不值得提倡,业务场景中应用Aop 无外乎 : 方法级权限、方法结果缓存、数据库事务、日志记录、性能统计