AOP简介java
AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充.。
AOP 的主要编程对象是 切面(aspect), 而切面模块化横切关注点.。
在应用 AOP 编程时, 仍然须要定义通用的系统功能, 但能够明确的定义这个功能在哪里, 以什么方式应用, 而且没必要修改受影响的类. 这样一来横切关注点就被模块化到特殊的对象(切面)里。
AOP的优势:web
AOP 中的专业术语spring
AOP的两种底层实现方式express
代理:apache
代理设计模式的原理: 使用一个代理对象将原始对象包装起来, 而后用该代理对象取代原始对象. 任何对原始对象的调用都要经过代理对象. 代理对象决定是否以及什么时候将方法调用转到原始对象上。编程
为每个目标对象建立一个代理实现类的方式能够认为就是静态代理。设计模式
静态代理的实现很简单,可是会形成代理类的快速膨胀,每个目标类,都须要建立一个代理类api
1 //静态代理 2 public class StaticProxyUserService implements UserService { 3 //原始对象 4 private UserService userService; 5 6 public StaticProxyUserService(UserService userService) { 7 this.userService = userService; 8 } 9 @Override 10 public User getById(String userId) { 11 System.out.println("执行权限校验,日志记录......."); 12 return userService.getById(userId); 13 } 14 @Override 15 public boolean add(User user) { 16 System.out.println("执行权限校验,日志记录......."); 17 return userService.add(user); 18 } 19 20 @Override 21 public boolean delete(String userId) { 22 System.out.println("执行权限校验,日志记录......."); 23 return userService.delete(userId); 24 } 25 @Override 26 public boolean update(User user) { 27 System.out.println("执行权限校验,日志记录......."); 28 return userService.update(user); 29 } 30 }
为了解决静态代理的缺点,就产生了动态代理:在系统运行时,动态生成一个持有原始对象,并实现代理接口的Proxy,同时 “植入”通用逻辑(日志、权限等)。maven
动态代理能够实现静态代理相同的功能,惟一的区别这些Proxy的建立都是自动的而且在系统运行时生成的。这样就不须要对每个原始对象来建立一个代理了。ide
JDK内置的Proxy动态代理能够在运行时动态生成字节码,而不必针对每一个类编写代理类。中间主要使用到了一个接口InvocationHandler与Proxy.newProxyInstance静态方法。 使用内置的Proxy(JDK动态代理)实现动态代理有一个问题:被代理的类必须实现接口,未实现接口则没办法完成动态代理。 若是项目中有些类没有实现接口,则不该该为了实现动态代理而刻意去抽出一些没有实例意义的接口,经过cglib能够解决该问题。 |
1. 建立maven工程并解决jdk版本及web.xml问题
2. 导入jar包
<properties> <spring-version>4.2.4.RELEASE</spring-version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring-version}</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance --> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring-version}</version> </dependency> </dependencies> <build> <plugins> <!-- 设置jdk的编译版本 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build>
3. 编写切面类(封装加强逻辑)
1 //切面:定义了加强的业务逻辑(权限验证) 2 public class SecurityAspect { 3 //权限校验的系统逻辑 4 public void checkPrivilege(){ 5 System.out.println("我是权限校验的方法,我须要在方法执行前进行执行"); 6 } 7 }
4. 建立代理对象
1 public class ProxyFactory implements InvocationHandler{ 2 //目标类 3 private Object target; 4 5 //传递目标对象 6 public ProxyFactory(Object target) { 7 super(); 8 this.target = target; 9 } 10 11 public Object getProxy(){ 12 /** 13 * loader:类加载器 14 * interfaces:目标实现类接口(jdk动态代理必须有接口) 15 * h:实现了InvocationHandle接口的类 16 */ 17 return Proxy.newProxyInstance(target.getClass().getClassLoader(), 18 target.getClass().getInterfaces(), this); 19 } 20 21 @Override 22 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 23 //添加校验权限的逻辑 24 SecurityAspect securityAspect = new SecurityAspect(); 25 //添加检验权限 26 securityAspect.checkPrivilege(); 27 //反射调用业务逻辑方法(目标类,参数) 28 Object result = method.invoke(target, args); 29 return result; 30 } 31 }
5. 测试
1 public static void main(String[] args) { 2 //测试动态代理的执行 3 UserService target = new UserServiceImpl(); 4 //产生代理对象 5 UserService proxy = (UserService) new ProxyFactory(target).getProxy(); 6 //调用代理对象的业务方法 7 proxy.add(); 8 }
CGLIB(Code Generation Library)是一个开源项目,是一个强大的,高性能,高质量的Code生成类库,它能够在运行期扩展Java类与实现Java接口,通俗说cglib能够在运行时动态生成字节码。 使用cglib完成动态代理,大概的原理是:cglib继承被代理的类(UserServiceImpl),重写方法,织入通知,动态生成字节码并运行,由于是继承因此final类是没有办法动态代理的。
|
1. 定义目标类(不须要实现接口)
1 /** 2 * cglib的目标类 3 * 没有实现接口,只是一个业务类 4 */ 5 public class UserServiceCglib { 6 //切入点 7 //业务逻辑方法 8 public void add(){ 9 System.out.println("cglib的add方法被调用..."); 10 } 11 }
2. 定义切面类(加强逻辑类)
1 /** 2 * 加强逻辑类:日志记录切面 3 */ 4 public class LogAspect { 5 //通知 6 //加强的业务逻辑 7 public void log(){ 8 System.out.println("日志记录... ..."); 9 } 10 }
3. 定义cglib动态代理生成器
1 /** 2 * cglib动态代理类生成器 3 */ 4 public class CglibProxyFactory implements MethodInterceptor{ 5 //目标对象 6 private Object target; 7 8 //有参构造器 9 public CglibProxyFactory(Object target) { 10 super(); 11 this.target = target; 12 } 13 14 //获取代理类的方法 15 public Object getProxy(){ 16 //调用cglib产生代理对象 17 Enhancer enhancer = new Enhancer(); 18 //设置父类的类型 19 enhancer.setSuperclass(target.getClass()); 20 //设置回调方法 21 enhancer.setCallback(this); 22 23 //产生代理对象 24 Object proxy = enhancer.create(); 25 return proxy; 26 } 27 28 //拦截业务方法的执行 29 @Override 30 public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 31 //添加加强逻辑 32 //添加日志 33 LogAspect logAspect = new LogAspect(); 34 logAspect.log(); 35 36 //执行业务逻辑方法 37 Object result = methodProxy.invokeSuper(o, args); 38 return result; 39 } 40 }
4. 测试
1 public static void main(String[] args) { 2 //建立目标对象 3 UserServiceCglib target = new UserServiceCglib(); 4 //获取目标对象的代理对象 5 UserServiceCglib proxy = (UserServiceCglib) new CglibProxyFactory(target).getProxy(); 6 proxy.add(); 7 }