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");
}
}

CgLib代理

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"); // 调用代理的方法
}
}

xml声明式

引入增强(如果某个类实现了 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动态代理)

基于注解:通过 AspectJ execution 表达式拦截方法

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:引入增强

基于注解:通过 AspectJ @annotation 表达式拦截方法

实现下牛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>

xml切 ,一点都不好用

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;
}
}
}

v1.1AOP

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 无外乎 : 方法级权限、方法结果缓存、数据库事务、日志记录、性能统计

Proxy 和aop的更多相关文章

  1. Spring3系列11- Spring AOP——自动创建Proxy

    Spring3系列11- Spring AOP——自动创建Proxy 在<Spring3系列9- Spring AOP——Advice>和<Spring3系列10- Spring A ...

  2. spring aop

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将 ...

  3. [转]彻底征服 Spring AOP 之 理论篇

    基本知识 其实, 接触了这么久的 AOP, 我感觉, AOP 给人难以理解的一个关键点是它的概念比较多, 而且坑爹的是, 这些概念经过了中文翻译后, 变得面目全非, 相同的一个术语, 在不同的翻译下, ...

  4. [Spring框架]Spring AOP基础入门总结一.

    前言:前面已经有两篇文章讲了Spring IOC/DI 以及 使用xml和注解两种方法开发的案例, 下面就来梳理一下Spring的另一核心AOP. 一, 什么是AOP 在软件业,AOP为Aspect ...

  5. Spring AOP小结

    一. AOP介绍 AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP ...

  6. java框架篇---spring AOP 实现原理

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  7. Spring的AOP与代理

    spring 支持两种注入方式: setter/constructor 支持多种配置方式: xml/java5注解/java类配置 支持两种事务管理: 声明性/编程性 实际上上述方式只有一个就能保证系 ...

  8. 菜鸟学习Spring——60s使用annotation实现简单AOP

    一.概述. AOP大家都知道切面编程,在Spring中annotation可以实现简单的AOP列子.下面还未大家介绍几个概念: Aspect 对横切性关注点的模块化. Advice 对横切性关注点的具 ...

  9. Spring AOP: Spring之面向方面编程

    Spring AOP: Spring之面向方面编程 面向方面编程 (AOP) 提供从另一个角度来考虑程序结构以完善面向对象编程(OOP). 面向对象将应用程序分解成 各个层次的对象,而AOP将程序分解 ...

随机推荐

  1. Python3读写JSON文件

    JSON简介 JSON(JavaScript Object Notation)即JavaScript对象表示法,一种轻量级,通用的文本数据格式. JSON语法支持对象(Object),数组(Array ...

  2. while 循环 continue break 用法例子

    py2 temp = "理解" # utf- 8 #解码, 需要指定原来的是什么编码 temp_unicode = temp.decode("utf-8") # ...

  3. springboot+mybatis+druid+sqlite/mysql/oracle

    搭建springboot+mybatis+druid+sqlite/mysql/oracle附带测试 1.版本 springboot2.1.6 jdk1.8 2.最简springboot环境 http ...

  4. Python经典练习题1:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

    Python经典练习题 网上能够搜得到的答案为: for i in range(1,85): if 168 % i == 0: j = 168 / i; if i > j and (i + j) ...

  5. Maven的New中没有Servlet问题(IDEA)

    1.问题 第一次使用Maven骨架创建Web项目的时候,遇到了 New 里面没有 servlet 的问题. 2.原因 经过查询,是因为IDEA检测到项目中没有导入相关的 jar 包导致. 3.解决方法 ...

  6. 《梁宁·产品思维30讲》课程学习笔记(内含全套音频+ppt资料

    科技进步.产品迭代.公司演化.组织变迁……不变的是用户的情绪和人性. 那些信奉“用户驱动”的人,从普通人变成了行业大佬,建立了自己的世界.乔布斯.马化腾.马云.雷军.张小龙.周鸿祎.傅盛……这些改变世 ...

  7. Flutter移动电商实战 --(17)首页_楼层区域的编写

    1.楼层标题组件 该组件非常简单,只接收一个图片地址,然后显示即可: class FloorTitle extends StatelessWidget { final String picture_a ...

  8. 工作流调度器之Azkaban

    Azkaban 1. 工作流调度器概述 1.1. 为什么需要工作流调度系统 一个完整的数据分析系统通常都是由大量任务单元组成:shell脚本程序,java程序,mapreduce程序.hive脚本等 ...

  9. CentOS查看每个进程的网络流量

    所需工具nethogs 安装:yum install -y nethogs 使用:nethogs eth0 sudo nethogs -s //按接收流量大小排序 如上图,PID一列就是进程的PID, ...

  10. Spring Boot项目中MyBatis连接DB2和MySQL数据库返回结果中一些字符消失——debug笔记

    写这篇记录的原因是因为我之前在Spring Boot项目中通过MyBatis连接DB2返回的结果中存在一些字段, 这些字段的元素中缺少了一些符号,所以我现在通过在自己的电脑上通过MyBatis连接DB ...