目录
一、代理模式
代理模式的好处:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
- 公共业务交给代理角色,从而实现业务的分工
- 公共业务发生扩展时,方便集中管理
- 代码耦合性降低
代理模式的缺点:
- 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率变低
静态代理:
角色分析:
- 抽象角色:一般会用接口或者抽象类来解决(例如租房 Rent)
- 真实角色:被代理的角色(例如房东:Host)
- 代理角色:代理真实角色,代理真实角色后,一般会做一些附属操作(例如租房中介)
- 客户:访问代理对象的人(例如买房的人)
动态代理:
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口——JOK动态代理
- 基于类——cglib
实现步骤:①创造一个类继承InvacationHandler,用这个类自动生成代理类
代码如下(模板基本可直接套用,只需改接口名和接口中的方法名):
//用这个类自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private UserService userService;
//注意重写set方法
public void setUserService(UserService userService) {
this.userService = userService;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),userService.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的实质————反射机制
Object result= method.invoke(userService,args);
return result;
}
}
②测试
public static void main(String[] args) {
//真实角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色:现在没有
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象!
pih.setUserService(userService);
UserService proxy= (UserService) pih.getProxy();
proxy.add();
}
二、AOP
1.相关概念及意义:
AOP: 面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分 之间的耦合性降低,提高程序的可重用性,同时提高开发效率
- 切面(Aspect):横切关注点 被模块化的特殊对象(即为一个类)
- 通知(Advice):切面必须要完成的工作(即类中的方法)
- 目标(Target):被通知的对象
- 代理(Proxy):向目标对象应用通知之后创建的对象
- 切入点(PointCut):切面通知执行的”地点“的定义
- 连接点(JointPoint):与切入点匹配的执行点
意义:AOP是一种横向编程的思想,在不影响原来业务类的情况下,实现动态的增强
2.使用Spring实现AOP
【重点】使用AOP织入,需要先导入依赖包!
代码如下:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
实现AOP的三种方式:
①使用Spring的API接口实现【主要是SpringAPI接口实现】
基本步骤:1、定义一个类(实现对应的前置增强或后置增强)
示例代码:
public class log implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName());
}
}
2、将类注册到Spring中
示例代码: <!-- advice-ref指向对应增强类 -->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* service.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>
</aop:config>
3.测试
示例代码(下同,不再重复演示):
public class MyTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext.xml");
UserService userService=(UserService) context.getBean("userService");
userService.add();
}
}
(注:动态代理代理的是接口,所以强转为UserService而不是UserServiceImpl)
②自定义来实现AOP【主要是切面定义】
基本步骤:1、自定义一个类,写方法用于增强
2、注册bean
示例代码:
<bean id="diy" class="diy.DiyPointCut"/>
<aop:config>
<!-- 自定义切面 ref为要引用的类 -->
<aop:aspect ref="diy">
<aop:pointcut id="point" expression="execution(* service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
<!-- method中引用的是定义的类中的方法,用于增强 -->
③使用注解实现
基本步骤:1、将所需增强的类前标注@Aspect (标注这个类是一个切面)
2、在写增强方法之前,在方法前标注@Before("execution(省略)")等区别通知类型
3、配置文件,把增强类注册到bean中 (或直接在类前加@Configuration)
示例代码:
<bean id="Aop" class="diy.aop"/>
<aop:aspectj-autoproxy/>
总结
记录Spring代理模式及AOP中的重点,方便以后复习巩固!