Spring入门第三讲 Spring中的代理 静态代理 动态代理(JDK代理) cglib代理(字节码增强) Spring中的AOP

Spring中的代理

概念:代理即在访问真正的对象之前和之后所做的业务处理的对象
以事务的操作为例讲解:

静态代理

​代理对象和真实的对象需要实现同一个接口

目标对象类
public class UserDaoImpl implements IUserDao {

	@Override
	public int saveUser() {
		//System.out.println("--开启事务--");
		System.out.println("--添加用户--");
		//System.out.println("--关闭事务--");
		return 0;
	}

	@Override
	public int delUser() {
		//System.out.println("--开启事务--");
		System.out.println("--删除用户--");
		//System.out.println("--关闭事务--");
		return 0;
	}
}
代理对象类
    public class ProxyUserDaoImpl implements IUserDao{

        //UserDaoImpl userDao = new UserDaoImpl();

        IUserDao userDao;

        public ProxyUserDaoImpl(IUserDao userDao){
            this.userDao = userDao;
        }

        @Override
        public int saveUser() {
            System.out.println("--开启事务--");
            userDao.saveUser();
            System.out.println("--关闭事务--");
            return 0;
        }

        @Override
        public int delUser() {
            System.out.println("--开启事务--");
            userDao.delUser();
            System.out.println("--关闭事务--");
            return 0;
        }
    }
测试类
@Test
public void test(){
    IUserDao userDao = new ProxyUserDaoImpl(new UserDaoImpl2());
    userDao.delUser();
    userDao.saveUser();
}

动态代理(JDK代理)

​ 在程序运行期间,动态的创建代理对象

//目标对象类与上述相同
//测试方法
@Test
public void test2(){
    //真实对象
    IUserDao userDao = new UserDaoImpl();
    //创建代理对象
    //ClassLoader		加载真实对象的class文件
    //Class<?>[] 		真实对象所实现的所有接口
    IUserDao proxy = (IUserDao) Proxy.newProxyInstance(
        userDao.getClass().getClassLoader(), 
        userDao.getClass().getInterfaces(), 
        //代理对象要做的事情
        new InvocationHandler(){
            //proxy 	代理对象
            //method	目标对象中的方法的描述方法
            //args		目标对象中方法的参数
            @Override
            public Object invoke(Object proxy, Method method,
                Object[] args) throws Throwable {
                System.out.println("开启事务");
                //每个要代理的方法都会执行
                //通过反射机制,找到要执行的dao里面的方法
                Object obj = method.invoke(userDao, args);
                System.out.println("关闭事务");
                return obj;
            }
        }
    );
    proxy.delUser();
    proxy.saveUser();
}

问题:必须要有接口

cglib代理(字节码增强)

导入jar,只需要提供要代理的类即可
jar:asm.jar cglib.jar或者使用Spring-core.jar(其中包含的有)

目标对象类
public class UserDaoImpl2 {

	public int saveUser() {
		//System.out.println("--开启事务--");
		System.out.println("--添加用户2--");
		//System.out.println("--关闭事务--");
		return 0;
	}

	public int delUser() {
		//System.out.println("--开启事务--");
		System.out.println("--删除用户2--");
		//System.out.println("--关闭事务--");
		return 0;
	}
}

测试类
@Test
public void tests3(){
    //创建目标对象
    UserDaoImpl2 userDaoImpl2 = new UserDaoImpl2();
    //创建Enhancer设置相关属性及创建代理对象--cglib
    Enhancer enhancer = new Enhancer();
    //指定要代理的对象
    enhancer.setSuperclass(UserDaoImpl2.class);
    //设置回调函数处理代理方法
    enhancer.setCallback(new MethodInterceptor(){
        public Object intercept(Object proxy,Method method,Object[] args,MethodProxy methodProxy){
            System.out.println("开启事务");
            Object obj = method.invoke(userDaoImpl2,args);
            //methodProxy.invokeSuper(proxy,args);
            System.out.println("关闭事务");
            return obj;
        }
    });
    //创建代理对象
    UserDaoImpl2 proxy = (UserDaoImpl2)enhancer.create();
    proxy.delUser();
    proxy.saveUser();
}

Spring中的AOP

1、面向切面编程:采用横向抽取的方式,在程序运行的过程中,动态的向目标对象中织入要增强的代码。底层采用动态代理方式(JDK代理和cglib代理)
在这里插入图片描述
2、应用场景

事务管理、日志、性能监控等…

3、术语解释

target:目标对象

advice:通知(增强代码)

joinpoint:连接点,可能要添加增强代码的方法

pointcut:切入点,要添加增强代码的方法

weaving:织入,将增强代码添加到切入点的过程

aspect:切面,切入点和增强代码之间形成的虚拟的面

4、案例–给删除方法添加事务管理,使用aspectj框架而非Spring aop

步骤:

a)创建项目,导入jar。

​ 4+1 core context bean spel jcl

​ spring-aop.jar 基于aspectj实现的

​ spring-aspects.jar aspectj的规则

​ aspectjweaver.jar 织入的技术

​ aopalliance.jar 设置通知的规则

b)创建目标类和通知类

public class UserServiceImpl implements UserService{
    @Override
        public int saveUser() {
            userDao.saveUser();
            return 0;
        }

        @Override
        public int delUser() {
            userDao.delUser();
            return 0;
        }
}

public class MyAdvice{
    //JoinPoint用于获取目标对象中的相关信息
    public void before(JoinPoint joinPoint){
        System.out.println("添加事务");
    }
    
    public void after(){
        System.out.println("关闭事务");
    }
    
    public void afterReturning(){
        System.out.println("后置通知");
    }
    
    public void afterThrowing(){
        System.out.println("异常通知");
    }
    //环绕通知,必须手动调用目标对象的方法
    public void around(ProceedingJoinPoint joinPoint){
        try{
            System.out.println("前置");
            joinPoint.proceed();
            System.out.println("返回");
        }catch(){
            System.out.println("异常");
        }finally{
            System.out.println("后置通知");
        }
    }
}
<!--创建目标对象-->
<bean id="userService" class=""></bean>
<!--创建增强类对象-->
<bean id="myAdvice" class=""></bean>
<!--将通知织入到目标对象上
	aop:config属性
		proxy-target-class="true" true代表强制使用cglib
-->
<aop:config>
	<!--切入点:配置要向什么地方添加增强代码
		expression:execution(返回值类型 包名 类名 方法名(参数,...))
			* service..*(..)
	-->
    <aop:pointcut expression="execution(* service..*(..))" id="myPointcut"/>
    <!--切面:添加什么,如何添加-->
    <aop:aspect ref="myAdvice">
        <!--前置通知-->
    	<!--<aop:before method="before" pointcut-ref="myPointcut"/>-->
        <!--后置通知-->
        <!--<aop:after method="after" pointcut-ref="myPointcut"/>-->
        <!--返回通知-->
        <!--<aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>-->
        <!--异常通知-->
        <!--<aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut"/>-->
        <!--环绕通知-->
        <aop:around method="around" pointcut-ref="myPointcut"/>
    </aop:aspect>
</aop:config>
//测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class AopTest{
    @Autowired
    UserService userService;
    
	@Test
    public void test(){
        userService.saveUser();
        userService.delUser();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值