黑马-Spring(IOC&DI) AOP

时间:2023-03-09 00:21:18
黑马-Spring(IOC&DI) AOP

黑马-Spring(IOC&DI) AOP

IOC(控制翻转)

概念

把对象的创建、初始化、销毁等工作交给spring容器来做

案例

环境

黑马-Spring(IOC&DI) AOP

步骤

1、  写一个HelloWorld类

2、  写一个配置文件   把hello类放到spring容器中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--
beans
一个bean代表一个类
所以beans就是很多个类
-->
<!--
一个类
id 标示符
class 类的全名
-->
<bean id="helloWorld" class="com.itheima09.spring.ioc.helloworld.HelloWorld">
</bean>
</beans>

applicationContext.xml

3、  客户端

package com.itheima09.spring.ioc.helloworld.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.itheima09.spring.ioc.helloworld.HelloWorld; public class HelloWorldTest {
@Test
public void testHello(){
HelloWorld helloWorld = new HelloWorld();
helloWorld.hello();
} @Test
public void testHello_Spring(){
/**
* 1、启动spring容器
* 2、从spring容器中把对象提取出来
* 3、对象调用方法
*/
//启动了spring容器了
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//从spring容器中把helloWorld对象提取出来了
HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
helloWorld.hello();
}
}

4、  说明:

Spring容器的作用就是为HelloWorld这个类创建对象

Spring容器的结构

黑马-Spring(IOC&DI) AOP

创建对象

构造函数(用的最多)

黑马-Spring(IOC&DI) AOP

静态工厂

关于静态工厂方法(https://www.jianshu.com/p/ceb5ec8f1174)

黑马-Spring(IOC&DI) AOP

实例工厂

黑马-Spring(IOC&DI) AOP

说明:

给工厂类创建了一个对象helloWorldFactory,再利用工厂对象调用工厂方法

别名

黑马-Spring(IOC&DI) AOP

对象的创建时机

案例

黑马-Spring(IOC&DI) AOP

执行步骤为1,3,2

helloword构造函数为什么调用3次

黑马-Spring(IOC&DI) AOP

以上两种情况是默认值,当spring容器启动的时候创建对象

在bean有这样一个属性

黑马-Spring(IOC&DI) AOP

意义

如果把lazy-init设置为true,则当spring容器启动的时候,检测不到任何错误,这样会存在很大的安全性隐患,所以一般情况下应该设置lazy-init为default/false。但是如果一个bean中有一个属性,该属性含有大量的数据,这个时候不希望该bean过早的停留在内存中。

这个时候需要用到lazy-init为true。

对象的scope

默认情况(scope=singleton)

黑马-Spring(IOC&DI) AOP

在默认情况下放入到spring中的bean是单例的

将来service层和dao层所有的类将放入到spring容器中,所以默认情况下这两个层的类的实例都是单例的,所以不能把数据声明到属性中。如果声明在属性中,将会成为共享的。

Scope为prototype

黑马-Spring(IOC&DI) AOP

创建时机和scope的结合

Scope为prototype,lazy-init为true

在context.getBean时创建对象

Scopse为prototype,lazy-init为false

在context.getBean时创建对象,lazy-init为false失效

当scpose为prototype时,始终在context.getBean时创建对象

Scopse为singleton

是默认情况

Init和destroy

黑马-Spring(IOC&DI) AOP

说明:

1、  init方法是由spring内部执行的

2、  只有当spring容器关闭以后才能执行destroy方法,spring容器一般情况下是不会关闭的。只有当web容器销毁掉的时候才可能关闭掉,所以只要一个对象在spring容器中,在spring容器关闭之前,会一直保留。

3、  如果一个bean的配置是scope为”prototype”,则spring容器不负责销毁。

Spring容器做的事情

黑马-Spring(IOC&DI) AOP

总结

创建对象

1、  对象的创建方式

2、  对象的创建时机

3、  对象的创建的模式

4、  Init和destroy

5、  创建时机和创建模式的结合

DI(依赖注入)

概念

给属性赋值

黑马-Spring(IOC&DI) AOP

给pid和name赋值的过程就是di

Xml

Setter方法

黑马-Spring(IOC&DI) AOP

说明:

1、  spring容器实例化person和student两个对象

2、  利用java的反射机制调用属性的setter方法赋值   property的 name属性由setter决定

3、  在客户端利用context.getBean方法把spring容器中的一个对象获取了。

黑马-Spring(IOC&DI) AOP

说明:

1、  启动spring容器

2、  实例化person对象和student对象

3、  给person中的属性赋值

4、  调用person的init方法初始化

5、  客户端利用context.getBean获取对象

黑马-Spring(IOC&DI) AOP

说明:

1、  启动spring容器

2、  实例化person对象

3、  因为person对象依赖于student对象,所以在实例化person对象的时候必须实例化student对象,所以这个时候,在student对象上的lazy-init为true将失效

黑马-Spring(IOC&DI) AOP

说明:

1、  启动spring容器

2、  实例化student

3、  在客户端执行context.getBean方法获取person对象

4、  实例化person对象,调用person的构造函数

5、  调用person中的setStudent方法,给person中的student赋值

6、  执行person中的init方法

7、  Person对象调用方法

构造器

黑马-Spring(IOC&DI) AOP

说明:

1、  constructor-arg代表指定的构造器函数的其中的一个参数

2、  可以利用index,ref,value,type来指定唯一的构造器

3、  如果一个bean的配置中没有constructor-arg属性,则必须利用默认的构造函数创建对象。

4、  所以在写一个javabean的时候,应该提供属性的setter方法,默认的构造器,带参数的构造器

IOC和DI的意义

案例1

需求

编写一个文档管理系统,在该系统中有如下的结构:

1、  Document:interface

readDocument方法

writeDocument方法

2、  WordDocument 是Document的实现类

readDocument

writeDocument

3、  ExcelDocument

readDocument

writerDocument

4、  PDFDocument

readDocument

writeDocument

5、  DocumentManager

Document  document;

readDocument()

writeDocument()

做法1

黑马-Spring(IOC&DI) AOP

说明:

上述的代码是不完全的面向接口编程

做法2

黑马-Spring(IOC&DI) AOP

说明:

在代码端没有出现具体的类,完全的面向接口编程。

在spring容器的配置文件中决定了documentManager中的接口的实现类是什么。而这个过程和java代码端没有关系。

案例2

需求

把action调用service,service调用dao用spring来完成

实现

黑马-Spring(IOC&DI) AOP

意义

实现了完全的面向接口编程,在代码端没有要关系一个接口的实现类是什么。

注解

概念

1、  用来解释说明

2、  注解必须作用在类的某一个部分

3、  注解的作用域范围(java,class,jvm)

4、  注解解析器

自定义的注解

黑马-Spring(IOC&DI) AOP

注解的使用

黑马-Spring(IOC&DI) AOP

注解解析器

package com.itheima09.annotation;

import java.lang.reflect.Method;

import org.junit.Test;

/**
* 注解解析器
* @author zd
*
*/
public class AnnotationParse {
public static void parse(){
Class classt = Itheima09.class;
//在该类上存在ClassInfo注解
if(classt.isAnnotationPresent(ClassInfo.class)){
//从类上得到类的注解
ClassInfo classInfo = (ClassInfo)classt.getAnnotation(ClassInfo.class);
//输出该注解的name属性
System.out.println(classInfo.name());
}
//获取该类的所有的方法
Method[] methods = classt.getMethods();
for(Method method:methods){
//如果该方法上存在MethodInfo注解
if(method.isAnnotationPresent(MethodInfo.class)){
//获取该方法上面的methodinfo注解
MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
//输出注解中的value属性
System.out.println(methodInfo.value());
}
}
} @Test
public void test(){
AnnotationParse.parse();
}
}

Spring中的注解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!--
把person和student放入到spring容器中
-->
<bean id="person" class="com.itheima09.spring.di.annotation.Person"></bean>
<bean id="student" class="com.itheima09.spring.di.annotation.Student"></bean>
<!--
启动依赖注入的注解解析器
-->
<context:annotation-config></context:annotation-config>
</beans>

applicationContext.xml

package com.itheima09.spring.di.annotation;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class PersonTest {
@Test
public void testPerson(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person)context.getBean("person");
person.say();
}
}

PersonTest

黑马-Spring(IOC&DI) AOP

在spring的配置文件中

黑马-Spring(IOC&DI) AOP

说明:

1、  启动spring容器

2、  spring容器内部创建了两个对象person和student

3、  当spring容器解析到

黑马-Spring(IOC&DI) AOP

启动依赖注入的注解解析器:

1、  spring容器在容器中查找所有的bean(prerson,student)

2、  看哪些bean的属性上面是否有Resource注解

3、  如果属性上面有该注解,再次检查是否有name属性

4、  如果没有name属性,则会把该注解标注的属性的名称获取到和spring容器中的id做匹配,如果匹配成功,则赋值,如果匹配不成功,则按照类型(注解的变量的类型 和 所有bean的class类型)进行匹配,如果匹配成功,则赋值(不推荐,类型匹配要求bean类型唯一出现,否则错误),如果匹配不成功,则报错。(赋值指的是person的private属性student的赋值,在Person类中对private属性student前面加上 Resource注解)

5、  如果有name属性,则把name属性的值解析出来和spring容器中的id做匹配,如果匹配成功,则赋值,如果匹配不成功,则报错。

6、  从上述的步骤可以看出注解的效率比较低,xml的效率比较高,注解书写比较简单,xml书写比较复杂。

Spring容器的关于di的注解(spring自己的注解)

按照类型匹配

黑马-Spring(IOC&DI) AOP

按照ID匹配

黑马-Spring(IOC&DI) AOP

注解只能应用与引用类型

类扫描的注解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!--
把一个类放入到spring容器中,该类就是一个component
在base-package指定的包及子包中扫描所有的类
-->
<context:component-scan base-package="com.itheima09.spring.scan.annotation">
</context:component-scan>
</beans>

xml

package com.itheima09.spring.scan.annotation;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

@Component("person")
public class Person {
@Resource(name="student")
private Student student;
public void say(){
this.student.say();
}
}

Person

步骤

黑马-Spring(IOC&DI) AOP

说明:在指定的包及子包中扫描

黑马-Spring(IOC&DI) AOP

黑马-Spring(IOC&DI) AOP

流程分析

1、  启动spring容器

2、  Spring容器解析类扫描的注解解析器,在base-package指定的包及子包中查找所有的类

3、  查看哪些类上面是否含有@Component注解

4、  如果该注解的value的属性的值为空,则把类名的第一个字母变成小写,作为id值,放入到spring容器中

5、  如果该注解的value的属性的值不为空,则用value的属性的值作为id值,放入到spring容器中

6、  再次查找在spring容器中的类的所有的属性,按照@Resource的规则给属性赋值

说明

使用了类扫描机制的做法,配置文件中的配置很简单了,但是效率越来越低。

继承

Xml的继承

黑马-Spring(IOC&DI) AOP

注解的继承

黑马-Spring(IOC&DI) AOP

Aop

目的

让PersonDao的数据库的操作和Transaction事务的操作分离。

代理模式

静态代理模式

package com.itheima09.dao.proxy;

public interface PersonDao {
public void savePerson();
}

interface

package com.itheima09.dao.proxy;

public class PersonDaoImpl implements PersonDao{
public void savePerson() {
System.out.println("save person");
}
}

impl

package com.itheima09.dao.proxy;

import com.itheima09.dao.Transaction;

public class PersonDaoProxy implements PersonDao{
private PersonDao personDao;
private Transaction transaction;
public PersonDaoProxy(PersonDao personDao,Transaction transaction){
this.personDao = personDao;
this.transaction = transaction;
}
public void savePerson() {
/**
* 1、开启事务
* 2、进行save操作
* 3、事务提交
*/
this.transaction.beginTransaction();
this.personDao.savePerson();
this.transaction.commit();
}
}

proxy

package com.itheima09.dao.proxy;

import org.junit.Test;

import com.itheima09.dao.Transaction;

public class ProxyTest {
@Test
public void testProxy(){
/**
* 创建PersonDaoImpl对象
* 创建事务对象
* 创建PersonDaoProxy对象
*/
PersonDao personDao = new PersonDaoImpl();
Transaction transaction = new Transaction();
PersonDaoProxy personDaoProxy = new PersonDaoProxy(personDao, transaction);
personDaoProxy.savePerson();
}
}

proxytest

黑马-Spring(IOC&DI) AOP

动态代理模式

Jdk动态代理

接口

黑马-Spring(IOC&DI) AOP

目标类

黑马-Spring(IOC&DI) AOP

拦截器

黑马-Spring(IOC&DI) AOP

客户端

黑马-Spring(IOC&DI) AOP

问题

1、  代理对象有多少方法,方法的名称是什么?

因为代理对象和目标类一样,同样的实现了接口,所以接口中有多少方法,代理对象中就有多少个方法,名称和接口中的方法的名称一样。

2、  拦截器中的invoke方法在什么时候执行的?

当在客户端,代理对象调用方法的时候,进入到了invoke方法

3、  拦截器中的invoke方法中的method参数在什么时候传递的值?

当在客户端,代理对象调用方法的时候,进入到了invoke方法,这个时候,method参数就是代理对象调用的方法。

4、  代理对象的方法体的内容是什么?

代理对象的方法体的内容就是invoke方法体的内容

代理对象的方法体:

1、  开启事务

2、  目标方法

3、  事务的提交

4、  代理对象的方法体就把事务和目标方法结合在一起了,这样做的目的就是为了让目标类的目标方法和事务的方法松耦合。

流程图

黑马-Spring(IOC&DI) AOP

案例

黑马-Spring(IOC&DI) AOP

目标接口
public interface SalaryManager {
public void showSalary();
}
目标类
package com.heima.dao.jdkproxy.salary;

public class SalaryManagerImpl implements SalaryManager{

    @Override
public void showSalary() {
System.out.println("正在查看工资"); } }
日志
package com.heima.dao.jdkproxy.salary;

public class Logger {
public void logging(){
System.out.println("logging");
}
}
安全性框架
package com.heima.dao.jdkproxy.salary;

public class Security {
public void security(){
System.out.println("security");
}
}
权限类
package com.heima.dao.jdkproxy.salary;

public class Privilege {
private String access; public void setAccess(String access) {
this.access = access;
} public String getAccess() {
return access;
}
}
拦截器
package com.heima.dao.jdkproxy.salary;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class SalaryManagerInterceptor implements InvocationHandler{
private Object target;
private Logger logger;
private Security security;
private Privilege privilege; public SalaryManagerInterceptor(Object target, Logger logger,
Security security, Privilege privilege) { this.target = target;
this.logger = logger;
this.security = security;
this.privilege = privilege;
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
this.logger.logging();
this.security.security();
if(this.privilege.getAccess().equals("admin")){
method.invoke(target, args);
}else{
System.out.println("权限不足");
}
return null;
} }

拦截器把这些内容全部结合在一起了。

改进

可以把日志、安全性框架等作为一个接口出现

日志:

黑马-Spring(IOC&DI) AOP

在拦截器中:

黑马-Spring(IOC&DI) AOP

Cglib代理

1、  产生的代理类是目标类的子类

2、  是用字节码增强技术产生的代理类

案例

jdkProxy缺点,  通知和目标方法结合在一起的过程,放在拦截器中,需要程序员自己指定(耦合性高),所以引入aop,可以再xml中配置,提高松耦合

Aop的概念

切面

事务、日志、安全性的框架,权限等就是切面

通知

切面中的方法就是通知

切入点

只有符合(表达式)切入点的条件,才能让通知和目标方法结合在一起

连接点

客户端调用的方法

织入

形成代理对象方法体的过程

黑马-Spring(IOC&DI) AOP

Aop的意义

黑马-Spring(IOC&DI) AOP

说明:

1、  在开发的过程中,日志、权限、安全性的框架、目标方法完全是松耦合的

2、  在形成代理对象的方法的过程中就把这几个结合在一起了

切入点表达式

黑马-Spring(IOC&DI) AOP

3.1 execution
由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如下是execution表达式的语法: execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
这里问号表示当前项可以有也可以没有,其中各项的语义如下: modifiers-pattern:方法的可见性,如public,protected;
ret-type-pattern:方法的返回值类型,如int,void等;
declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
name-pattern:方法名类型,如buisinessService();
param-pattern:方法的参数类型,如java.lang.String;
throws-pattern:方法抛出的异常类型,如java.lang.Exception;
如下是一个使用execution表达式的例子: execution(public * com.spring.service.BusinessObject.businessService(java.lang.String,..))
上述切点表达式将会匹配使用public修饰,返回值为任意类型,并且是com.spring.BusinessObject类中名称为businessService的方法,方法可以有多个参数,但是第一个参数必须是java.lang.String类型的方法。上述示例中我们使用了..通配符,关于通配符的类型,主要有两种: *通配符,该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。
如下示例表示返回值为任意类型,在com.spring.service.BusinessObject类中,并且参数个数为零的方法: execution(* com.spring.service.BusinessObject.*())
下述示例表示返回值为任意类型,在com.spring.service包中,以Business为前缀的类,并且是类中参数个数为零方法: execution(* com.spring.service.Business*.*())
..通配符,该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中,如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。
如下示例表示匹配返回值为任意类型,并且是com.spring.service包及其子包下的任意类的名称为businessService的方法,而且该方法不能有任何参数: execution(* com.spring.service..*.businessService())
这里需要说明的是,包路径service..*.businessService()中的..应该理解为延续前面的service路径,表示到service路径为止,或者继续延续service路径,从而包括其子包路径;后面的*.businessService(),这里的*表示匹配一个单词,因为是在方法名前,因而表示匹配任意的类。 如下示例是使用..表示任意个数的参数的示例,需要注意,表示参数的时候可以在括号中事先指定某些类型的参数,而其余的参数则由..进行匹配: execution(* com.spring.service.BusinessObject.businessService(java.lang.String,..))

execution

https://www.cnblogs.com/zhangxufeng/p/9160869.html

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

这里问号表示当前项可以有也可以没有,其中各项的语义如下:

  • modifiers-pattern:方法的可见性,如public,protected;
  • ret-type-pattern:方法的返回值类型,如int,void等;
  • declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
  • name-pattern:方法名类型,如buisinessService();
  • param-pattern:方法的参数类型,如java.lang.String;
  • throws-pattern:方法抛出的异常类型,如java.lang.Exception;
  • ..通配符,该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中,如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。
    • *通配符,该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。

黑马-Spring(IOC&DI) AOP

?表示可选可不选  可以不填

必须写 有2个:   1  ret-type-pattern:方法的返回值类型,如int,void等;

2

  • name-pattern:方法名类型,如buisinessService();
  • param-pattern:方法的参数类型,如java.lang.String;

黑马-Spring(IOC&DI) AOP

代表所有的公共方法

黑马-Spring(IOC&DI) AOP

代表所有的以set开头的方法

黑马-Spring(IOC&DI) AOP

代表com.xyz.service包下的AccoutService类的所有的方法

黑马-Spring(IOC&DI) AOP

代表com.xyz.service包下的所有的类的所有的方法

黑马-Spring(IOC&DI) AOP

代表com.xyz.service包及子包下的所有的类的所有的方法

黑马-Spring(IOC&DI) AOP

代表com.itheima.spring.aop.xml包下的所有的类的有三个参数,第一个参数为Long,第二个参数为String,第三个参数为任意类型的所有的方法

黑马-Spring(IOC&DI) AOP

黑马-Spring(IOC&DI) AOP

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

Spring的aop

步骤

目标接口

黑马-Spring(IOC&DI) AOP

目标类

黑马-Spring(IOC&DI) AOP

切面

黑马-Spring(IOC&DI) AOP

Spring的配置文件

黑马-Spring(IOC&DI) AOP

执行流程

黑马-Spring(IOC&DI) AOP

1、  context.getBean时,如果该类没有生成代理对象,则返回对象本身

2、  如果产生了代理对象,则返回代理对象

如果目标类实现了接口,则采用jdkproxy生成代理对象,如果目标类没有实现接口,则采用cglibproxy生成代理对象,而生成代理对象是由spring容器内部完成的。

通知

前置通知

在目标方法执行之前执行。

黑马-Spring(IOC&DI) AOP

后置通知

在目标方法执行之后执行

可以获取目标方法的返回值

当目标方法遇到异常,不执行

黑马-Spring(IOC&DI) AOP

黑马-Spring(IOC&DI) AOP

最终通知

无论目标方法是否遇到异常都会执行,相当于代码中的finnaly

异常通知

获取目标方法抛出的异常

黑马-Spring(IOC&DI) AOP

环绕通知

能够控制目标方法的执行

黑马-Spring(IOC&DI) AOP

黑马-Spring(IOC&DI) AOP

package com.heima.spring.aop.xml.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint; public class Transaction {
public void begeinTransaction(JoinPoint joinPoint){
System.out.println(joinPoint.getTarget());
System.out.println(joinPoint.getArgs());
System.out.println(joinPoint.getSignature().getName());
System.out.println("begin transaction");
}
public void commit(JoinPoint joinPoint,Object val){
System.out.println(val);
System.out.println("commit");
}
public void finalyMethod(JoinPoint joinPoint){ System.out.println("finaly method");
}
public void throwingMethod(JoinPoint jp,Throwable ex){
System.out.println(ex.getMessage());
System.out.println("异常"); }
public void arroundMethod(ProceedingJoinPoint pjp)throws Throwable{
System.out.println("环绕通知aaa");
pjp.proceed();
System.out.println("环绕通知bbbb");
}
}

xml

案例:异常处理

技术图

黑马-Spring(IOC&DI) AOP

实现

切面

黑马-Spring(IOC&DI) AOP

目标类

黑马-Spring(IOC&DI) AOP

配置

黑马-Spring(IOC&DI) AOP

从配置中可以看出,把service层所有的类当成目标类,只要service层所有的类的所有的方法抛出异常,则exceptionAspect中的异常通知就会获取到目标方法抛出的异常,所以在这里异常通知就是用来处理异常的,而且只有一个方法。并且该切面和所有的其他类都是松耦合的。

案例:权限的处理

技术图

黑马-Spring(IOC&DI) AOP

组成

1、  写dao层和service层的类和接口

2、  自定义的注解@PrivilegeInfo

3、  注解解析器:解析目标方法上面的注解的name属性的值

4、  写一个权限类Privilege(name)

5、  写一个关于权限的判断的切面,在切面中写一个环绕通知

实现

参照:/day03-02-itheima09-springAOP-xml-ex-privilege

扩展作业

利用spring的aop的环绕通知,记录如下的信息:

目标类     目标方法     执行时间   方法的起始时间  方法的结束时间

把上述的几个内容保存在数据库中,用jfreechar或者用table显示出来

AOP注解(了解)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<context:component-scan base-package="com.itheima09.springaop.annotation.transaction"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

xml

package com.itheima09.springaop.annotation.transaction;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; /**
* @Aspect
* ==
* <aop:config>
* <aop:pointcut
expression="execution(* com.itheima09.springaop.annotation.transaction.PersonDaoImpl.*(..))"
id="aa()"/>
* </aop:config>
* @author zd
*
*/
@Component("transaction")
@Aspect//说明该注解标注的类是一个切面类
public class Transaction { @Pointcut("execution(* com.itheima09.springaop.annotation.transaction.PersonDaoImpl.*(..))")
private void aa(){} //方法标签 修饰符最好是private 返回值必须是void @Before("aa()")
public void beginTransaction(){
System.out.println("begin transaction");
}
@AfterReturning(value="aa()",returning="ex")
public void commit(JoinPoint joinPoint,Object ex){
System.out.println("commit");
}
}

transaction