Spring学习5
一、代理模式
代理模式就是AOP的底层!
1.代理模式的分类
- 静态代理
- 动态代理
2.静态代理
角色分析:
- 抽象角色:一般使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色后,一般会做一些附属操作
- 客户:访问代理对象
2.1、接口
//租房
public interface Rent {void rent();
}
2.2、真实角色
//房东
public class Host implements Rent{public void rent() {System.out.println("房东需要出租房子!");}
}
2.3、代理角色
public class Proxy implements Rent{private Host host;public Proxy() {}public Proxy(Host host) {this.host = host;}public void rent() {seeHouse();host.rent();contract();fare();}//看房public void seeHouse(){System.out.println("中介带客户看房!");}//收中介费public void fare(){System.out.println("中介收取中介费!");}//签合同public void contract(){System.out.println("签租赁合同");}
}
2.4、客户端访问代理角色
public class Client {public static void main(String[] args) {//房东需要租房子Host host = new Host();//代理,中介帮房子租房子,但是中介会有一些附属操作Proxy proxy = new Proxy( host );//客户不需要找房东,找中介即可!proxy.rent();}
}
3.静态代理的好处
- 使真实角色更加纯粹,不去关注一些公共的业务
- 公共业务就交给了代理角色,实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
4.静态代理的缺点
- 一个真实角色就会产生一个代理对象,代码量会翻一倍,因此开发效率就会变低
二、动态代理
- 动态代理的角色和静态代理角色一样
- 动态代理的代理类是动态生成的
1.动态代理的分类
- 基于接口的动态代理
- 基于类的动态代理
2.基于接口的动态代理
- JDK动态代理
3. 基于类的动态代理
- cglib
4.动态代理的好处
- 使真实角色更加纯粹,不去关注一些公共的业务
- 公共业务就交给了代理角色,实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
- 一个动态代理类代理接口,一个接口一般对应一类业务
- 一个动态代理类可以代理多个类,只要是实现一个接口即可
三、AOP
AOP(Aspect Oriented Programming),面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中一个热点,也是Spring框架的一个核心,是函数式编程的一种衍生范式。利用AOP可以对业务各个部分进行隔离,从而使得业务逻辑各部分之间得耦合度降低,提高程序得可重用性,同时提高开发的效率。
四、AOP在Spring中的作用
提供声明式事务:允许用户自定义切面
- 横切关注点:跨域应用程序多个模块的方法或功能。与业务逻辑无关,但是需要关注的部分,就是横切关注点。如日志、安全、缓存、事务等等
- 切面(ASPECT):横切关注点 被模块化的特殊对象(是一个类)【Log】
- 通知(Advice):切面必须要完成的工作(是一个类中的方法)【Log中的方法】
- 目标(Target):被通知的对象
- 代理(Proxy):向目标对象应用通知后创建的对象
- 切入点(PointCut):切面通知执行的 “地点”的定义
- 连接点(JoinPoint):与切入点匹配的执行点
五、使用Spring实现AOP
- 导包
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.19</version></dependency>
- 方式一:使用Spring的API接口
public interface UserService {void add();void delete();void update();void query();
}
public class UserServiceImpl implements UserService{public void add() {}public void delete() {}public void update() {}public void query() {}
}
//前置日志
public class Log implements MethodBeforeAdvice {//method:要执行的目标对象的方法//objects:参数//o:目标对象public void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行");}
}
//后置日志
public class AfterLog implements AfterReturningAdvice {//o:返回值public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {}
}
配置类applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 注册bean--><bean id="userService" class="com.rxj.service.UserServiceImpl"/><bean id="log" class="com.rxj.log.Log"/><bean id="afterLog" class="com.rxj.log.AfterLog"/><!-- 配置aop:需要导入aop约束--><aop:config>
<!-- 切入点:expression表达式,execution(要执行的位置!)--><aop:pointcut id="pointcut" expression="execution(* com.rxj.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕增强--><aop:advisor advice-ref="log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/></aop:config>
</beans>
测试:
public class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" );//动态代理的是接口UserService userService = (UserService) context.getBean( "userService");userService.add();}
}
- 第二种方式:自定义是实现AOP
public interface UserService {void add();void delete();void update();void query();
}
public class UserServiceImpl implements UserService{public void add() {}public void delete() {}public void update() {}public void query() {}
}
public class DiyPointCut {public void before(){System.out.println("------方法执行前!------");}public void after(){System.out.println("------方法执行后!------");}
}
配置文件:
<!-- 方式二--><bean id="diy" class="com.rxj.diy.DiyPointCut"/><aop:config>
<!-- 自定义切面,ref 要引用的类--><aop:aspect ref="diy">
<!-- 切入点--><aop:pointcut id="point" expression="execution(* com.rxj.service.UserServiceImpl.*(..))"/>
<!-- 通知--><aop:before method="before" pointcut-ref="point"/><aop:after method="after" pointcut-ref="point"/></aop:aspect></aop:config>
测试:
public class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" );//动态代理的是接口UserService userService = (UserService) context.getBean( "userService");userService.add();}
}