Spring容器07AOP

源码参考:github上的code4craft/tiny-spring项目。

tiny-spring-step-7-method-interceptor-by-jdk-dynamic-proxy

解析

必看参考:
JDK动态代理上
JDK动态代理中
JDK动态代理下

静态代理

在这里插入图片描述

其实就是在代理对象内部调用了目标对象的方法。

在这里插入图片描述

public interface Calculator {
	int add(int a, int b);
}

public class CalculatorImpl implements Calculator {
	//加
	public int add(int a, int b) {
		int result = a + b;
		return result;
	}
}

public class CalculatorProxy implements Calculator {
        //代理对象内部维护一个目标对象引用
	private Calculator target;
        
        //构造方法,传入目标对象
	public CalculatorProxy(Calculator target) {
		this.target = target;
	}
        //调用目标对象的add,并在前后打印日志
	@Override
	public int add(int a, int b) {
		System.out.println("add方法开始...");
		int result = target.add(a, b);
		System.out.println("add方法结束...");
		return result;
	}
	
	public static void main(String[] args) {
		//把目标对象通过构造器塞入代理对象
		Calculator calculator = new CalculatorProxy(new CalculatorImpl());
		//代理对象调用目标对象方法完成计算,并在前后打印日志
		calculator.add(1, 2);
		calculator.subtract(2, 1);
	}
}

问题:

  1. 静态代理我们要为每一个要增强的类写代理类,代码冗余。
  2. 如果修改了某个接口,要修改很多的地方,耦合度很高。
  3. 如果要修改增强的方法,代理类多的话,需要改非常多的地方。

JDK动态代理

在这里插入图片描述

动态的是实现方法的增强,则不需要手动的创建接口的实现类。使用API提供的Proxy类为我们创建一个代理类,美滋滋。(接口没有方法体,没有构造方法)

//创建Class对象
Class<?> proxyClass = Proxy.getProxyClass(ProxyTest.class.getClassLoader(), Calc.class);
//获取构造方法
Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
//创建代理对象
Calc instance = (Calc)constructor.newInstance(new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String typeName = proxy.getClass().getTypeName();
        System.out.println("simpleName = " + typeName);
        String name = method.getName();
        System.out.println("name = " + name);
        return 1;
    }
});

事务案例

public interface UserService {
	void getUser();
}

@MyTransactional
public class UserServiceImpl implements UserService {
	@Override
	public void getUser() {
		System.out.println("service执行...");
	}
}

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTransactional {
}

public class ProxyFactoryBean {
	//通知
	private TransactionManager txManager;
	//目标对象
	private Object target;

	public void setTxManager(TransactionManager txManager) {
		this.txManager = txManager;
	}

	public void setTarget(Object target) {
		this.target = target;
	}

	//传入目标对象target,为它装配好通知,返回代理对象
	public Object getProxy() {
		Object proxy = Proxy.newProxyInstance(
				target.getClass().getClassLoader(),/*1.类加载器*/
				target.getClass().getInterfaces(), /*2.目标对象实现的接口*/
				new InvocationHandler() {/*3.InvocationHandler*/
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						try {
							//1.开启事务
							txManager.beginTransaction();
							//2.执行操作
							Object retVal = method.invoke(target, args);
							//3.提交事务
							txManager.commit();
							//4.返回结果
							return retVal;
						} catch (Exception e) {
							//5.回滚事务
							txManager.rollback();
							throw new RuntimeException(e);
						} finally {
							//6.释放连接
							txManager.release();
						}

					}
				}
		);
		return proxy;
	}

}

public class BeanFactory {

	public Object getBean(String name) throws Exception {
		//得到目标类的Class对象
		Class<?> clazz = Class.forName(name);
		//得到目标对象
		Object bean = clazz.newInstance();
		//得到目标类上的@MyTransactional注解
		MyTransactional myTransactional = clazz.getAnnotation(MyTransactional.class);
		//如果打了@MyTransactional注解,返回代理对象,否则返回目标对象
		if (null != myTransactional) {
			ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
			TransactionManager txManager = new TransactionManager();
			txManager.setConnectionUtils(new ConnectionUtils());
			//装配通知和目标对象
			proxyFactoryBean.setTxManager(txManager);
			proxyFactoryBean.setTarget(bean);
			Object proxyBean = proxyFactoryBean.getProxy();
			//返回代理对象
			return proxyBean;
		}
		//返回目标对象
		return bean;
	}
}

public class AOPTest {
	public static void main(String[] args) {
		BeanFactory beanFactory = new BeanFactory();
		try {
			Object bean = beanFactory.getBean("com.demo.myaopframework.service.UserServiceImpl");
			System.out.println(bean.getClass().getName());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

本文只是本人做笔记使用,不代表任何培训教学含义。看不懂的别问我,问了我也不会回答。溜了溜了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值