循序渐进AOP 04

首先我们准备一下用于演示的代码:以模拟MVC模式的经典架构来解释

pojo层

@Repository
public void User{
    private String name;
}

Dao层接口以及实现类

public interface UserDao{
   public void saveUser(User user);
} 
@Component
public class UserDaoImpl implements UserDao{
  @Override
   public void saveUser(User user){
       System.out.println("保存了一个用户:"+user);
}
}

Service层接口以及实现类

 public interface Uservice{
 public void saveUser(User user;
}
@Service
public class UserServiceImpl implements UserService{
@Autowired
 private UserDao userDao;
public void saveUser(User user){
  userDao.saveUser(user);
}
}

Servlet 层

@Controller
public class UserServlet{
@Autowired
private UserServcie userService;
public void saveUser(User user){
  userService.saveUser(user);
}
}

事务类

@Component
public class TxManager{
 public void begin(){
System.out.println("开启了事务");
}
public void commit(){
System.out.println("提交了事务");
}
}




一、静态代理

  要求代理类和被代理的类有相同的方法,因此我们在创建代理类的时候要和被代理的类实现相同的接口。

 要求将事务处理横向放入service层而且做到神不知鬼不觉

@Service("userService")
public class StaitcProxy{
//在代理类中添加目标对象,因为要执行目标类中的方法(也就是被代理类中的方法)
@Autowired
 @Qulifier("userServiceImpl")
private UserService target;
//添加事务代码
@Autowired
private  TxManager txmanager;
@Override
public void saveUser(User user){
txmanager.begin();
target.saveUser(user);
txmanager.commit();
}
}

测试类

pulbic class Mytest{
@Test
public void Test(){
ApplicationContext context=ClassPathXmlApplicationContext("applicationContext.xml");
User user = context.getBean(User.class);
UserServlet userServlet = context.getBean(UserServlet.class);
userServlet.saveUser(user);
}
}

输出的结果是

开启了事务
保存了一个用户:user=null;
提交了事务
有上述模拟测试可知:静态代理降低了耦合度,但是在如果每一个方法都需要事务,就需要创建很多的代理类,代码复用性大大降低。因此出现了动态代理:首先模拟一下JDK提供的动态代理:

   1首先我们需要创建一个动态的代理类,并创建获取被代理的类对象的方法

public class JDkDynamicProxy{
private TxManager txmanager;
//构造方法中为事务对象赋值
public JDKDynamicProxy(){
  txmanager = new TxManager;
}
//创建代理实例对象的方法
public Object getProxy(final Object target){
//创建一个代理实例对象 参数介绍:1.类加载器为了创建相同功能的类
//2.目标类的接口   3.回调参数 代理对象执行任何方法的时候会回调
Object proxyObject=Proxy.newProxyInstance(target.getClass().getClassLoader,target.getClass.getInterface,newInvocationHandler(){
@Override
public Object invoke(Object proxy,Method method,Object[] agrs) throws throwable{
txmanager.begin();
Object result = method.invoke(target,args);
txmanager.commit();
return result;
}
});
return proxy;
}
}

JDK提供的动态代理解决了复用性问题,需要添加事务的时候会自动创建代理类,执行相关的操作。那么新的问题又来了,如果一个类没有接口那么此代理便不能使用。这就引出了CGLib动态代理,这是由Spring框架提供的动态代理,接下来我们来模拟演示一下:

//创建一个动态代理类,声明一个获取代理对象的方法
public static Object getProxy(final Object target,final Txmanager txmanager){
//创建一个增强器
Enhancer enhancer = new Enhancer();
//通过增强器设置接口
enhance.setInterface(target.getClass().getInterfaces());
//通过增强器获取父类
enhance.setSuperclass(target.getClass());
//设置回调
enhance.setCallback(new MethodInterceptor(){
@Override
public Object interceptor(Object proxy,Method method,Object[] args,MthodProxy arg3){
txmanaget.begin();
Object result = method.invoke(target,args);
txmanager.commit();
return result;
}
});
return enhance.create();
}
以上通过代理进行横向植入并不能进行对被代理对象方法的过滤,就比如将事务植入service层,service层中所有方法都要被植入事务,但是需求并不可能都要求如此。这时Spring框架中AOP就可以弥补这种缺陷。接下来我们来演示一下:

//创建事务切面类和通知方法
@Component
pulic class TxAspect{
     //添加事务对象
    @Autowired
   private TxManager txmanger;
        //通知方法 我们用环绕通知,这样可以控制目标类方法的执行。
public void around(ProceedingJoinPoint joinPoint){
txmanager.begin();
//执行目标中的方法
txmanager.proceed();
txmanager.commit();
}
}
Spring核心配置文件:

<!--配置AOP-->
<aop:config>
       <!--配置切入点-->
        <aop:ponitcut expression="within(cn.tedu.sevice.*) id="pc"/>
         <!--配置切面-->
         <aop:aspect ref="txAspect">
                 <!--通知方法-->
                 <aop:around method="around" pointcut-ref="pc"/>
         </aop:aspect
</aop:config>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值