源码参考: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);
}
}
问题:
- 静态代理我们要为每一个要增强的类写代理类,代码冗余。
- 如果修改了某个接口,要修改很多的地方,耦合度很高。
- 如果要修改增强的方法,代理类多的话,需要改非常多的地方。
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();
}
}
}
本文只是本人做笔记使用,不代表任何培训教学含义。看不懂的别问我,问了我也不会回答。溜了溜了。