2021.07.07
Spring
优点
-
Spring是一 个开源的免费的框架(容器)
-
Spring是一 个轻量级的、非入侵式的框架!
-
控制反转(I0C),面向切面编程(AOP)
IOC: 控制反转,把创建对象过程交给Spring进行管理。
Aop: 面向切面,不修改源代码进行功能增强。
-
支持事务的处理,对框架整合的支持
IOC
变量名
的对象
相当于给对象中的属性设置一个值(属性的注入)
name
属性名 建议养成一个习惯 小写类名
ref
引用Spring容器中创建好的对象
value
具体的值,基本数据类型
<bean id="hello" class="com.Huiex.pojo.Hello">
<property name="str" value="Spring"/>------把str属性附了值为“Spring” 用set方法进行注入
</bean>
这个过程就叫控制反转:
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.
反转:程序本身不创建对象,而变成被动的接收对象
依赖注入:就是利用set方法来进行注入的.
IOC是-种编程思想 ,由主动的编程变成被动的接收 .
所谓的IOC,一句话搞定:对象由Spring来 创建,管理,装配
IOC创建对象的方式
使用无参构造
默认使用无参构造
//@AllArgsConstructor
public class User {
//Lombok 永远滴神
@Getter
@Setter
private String name;
public void show(){
System.out.println("name" + name);
}
}
在deans.xml文件中
<bean id="User" class="com.Huiex.pojo.User">
<property name="name" value="胖子君"/>
</bean>
使用有参构造
@AllArgsConstructor----------------------------------------------------------有参构造
public class User {
//Lombok 永远滴神
@Getter
@Setter
private String name;
public void show(){
System.out.println("name" + name);
}
}
1.下标赋值
<bean id="User" class="com.Huiex.pojo.User">
<constructor-arg index="0" value="下标赋值"/>
</bean>
2.参数名
<bean id="User" class="com.Huiex.pojo.User">
<constructor-arg name="name" value="参数名赋值"/>
</bean>
IOC使用对象
通过context.getBean
方法,创造出User对象(实际上是在IOC容器中取出对象)
@Test
public void Test(){
//得到IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//从IOC容器中取出
User user = (User) context.getBean("User");//强转一下
user.show();
}
在配置文件加载的时候,容器中管理的对象就已经初始化了
Spring配置文件
applicationContext.xm
官方文档中的Spring配置文件(beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
alias别名
没什么好说的
就是将bean的id起一个别名
<bean id="User" class="com.Huiex.pojo.User">
<constructor-arg name="name" value="参数名赋值"/>
</bean>
<alias name="User" alias="userNew"/>--------------------------------------起一个别名
@Test
public void Test(){
//得到IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("userNew");-----------------------------使用别名
user.show();
}
Bean的配置
id
: bean的唯一 标识符,相当于对象名
class
: bean 对象所对应的全限定名:包名+类型
name
:也是别名,而且name可以同时取多个别名(三个名字 User, user1 ,user2)
<bean id="User" class="com.Huiex.pojo.User" name="user1,user2">
<constructor-arg name="name" value="bean标签"/>
</bean>
import
这个import, 一般用于团队开发使用,他可以将多个配置文件,导入合并为一个
假设,现在项目中有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利
用import将所有人的beans.xml合并为一个总的!
资源目录下有多个bean配置文件,applicationContext.xml为主
resources目录下
applicationContext.xml
beans.xml
bean2.xml
bean3.xml
在applicationContext.xml中用import
标签导入其他配置文件
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="beans.xml"/>
<import resource="bean2.xml"/>
<import resource="beans.xml"/>
</beans>
仍然可以通过主配置文件applicationContext.xml创建其他beans.xml文件的对象
@Test
public void Test(){
//得到IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user2");//强转一下
user.show();
}
属性注入XML
构造器注入
使用无参构造
默认使用无参构造
//@AllArgsConstructor
public class User {
//Lombok 永远滴神
@Getter
@Setter
private String name;
public void show(){
System.out.println("name" + name);
}
}
在deans.xml文件中
<bean id="User" class="com.Huiex.pojo.User">
<property name="name" value="胖子君"/>
</bean>
使用有参构造
@AllArgsConstructor----------------------------------------------------------有参构造
public class User {
//Lombok 永远滴神
@Getter
@Setter
private String name;
public void show(){
System.out.println("name" + name);
}
}
1.下标赋值
<bean id="User" class="com.Huiex.pojo.User">
<constructor-arg index="0" value="下标赋值"/>
</bean>
2.参数名
<bean id="User" class="com.Huiex.pojo.User">
<constructor-arg name="name" value="参数名赋值"/>
</bean>
依赖(set)注入
使用Set方法注入
就是JavaBean中的set方法
@Data//yyds
public class Address {
private String name;-----------------------------------------空值
private User user;-------------------------------------------引用类(对象)
private String[] books;--------------------------------------数组
private List<String> hobbys ;--------------------------------List
private Map<String,String> card;-----------------------------Map
private Set<String> games;-----------------------------------集合
private String wife;-----------------------------------------字符串(null)
private Properties info;-------------------------------------一个特殊的类型(不重要)
}
头文件
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="beans.xml"/>
<!-- Bean注入,也就是属性是对象,从bean中(IOC容器)里面的对象-->
<bean id="Address" class="com.Huiex.pojo.Address">
引用类
Bean注入,也就是属性是对象
ref
属性 从bean中(IOC容器)里面的对象
<!-- 引用类(对象)-->
<property name="user" ref="user1"/>
数组
<!-- 数组-->
<property name="books">
<array>
<value>易点</value>
<value>易圈</value>
<value>等风</value>
</array>
</property>
列表
<!-- list-->
<property name="hobbys">
<list>
<value>0</value>
<value>3</value>
<value>7</value>
</list>
</property>
Map
<!-- Map-->
<property name="card">
<map>
<entry key="H" value="恒"/>
<entry key="e" value="易"/>
</map>
</property>
集合
<!-- set-->
<property name="games">
<set>
<value>z</value>
<value>J</value>
<value>L</value>
</set>
</property>
null
<!-- null-->
<property name="wife">
<null/>
</property>
空值
<!-- 空值-->
<property name="name" value=""/>
property
这个类型和map差不多只不过只有key
,value
x写在标签外面
<!-- property-->
<property name="info">
<props>
<prop key="username">root</prop>
<prop key="password">183303</prop>
</props>
</property>
</bean>
</beans>
扩展方法注入
P命名空间注入
xmlns:p="http://www.springframework.org/schema/p" 从官网找的
通过无参构造器注入:
<?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:p="http://www.springframework.org/schema/p"----------------------配置
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="Hello" class="com.Huiex.pojo.Hello" p:str="通过无参"/>
-----------------将”通过无参“赋值给`str`属性
</beans>
C命名空间注入
xmlns:c="http://www.springframework.org/schema/c" 也是从官网找的,明白我什么意思吗
通过有参构造器注入:
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="Hello" class="com.Huiex.pojo.Hello" c:str="通过有参构造"/>
</beans>
Bean的自动装配
-
自动装配是Spring满足bean依赖一种方式
-
Spring会在上下文中自动寻找,并自动给bean装配属性
-
在Spring中有三种装配的方式
1.在xml中显示的配置
2.在java中显示配置
3.隐式的自动装配bean
常规的手动装配
@Data
public class People {
private String name;
private Dog dog;
private Cat cat;
}
<bean id="dog" class="com.Huiex.pojo.Dog"/>
<bean id="cat" class="com.Huiex.pojo.Cat"/>
<bean id="People" class="com.Huiex.pojo.People">
<property name="name" value="胖子君"/>
<property name="cat" ref="cat"/>---------------------------利用ref引用IOC中的dog对象
<property name="dog" ref="dog"/>
</bean>
byname
- byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id
- byname的时候,需要保证所有bean的id唯一, 并且这个bean需要和自动注入的属性的set方法的值一致
<bean id="dog" class="com.Huiex.pojo.Dog"/>---------------------------重点小写 dog
<bean id="cat" class="com.Huiex.pojo.Cat"/>
<bean id="People" class="com.Huiex.pojo.People" autowire="byName">
<property name="name" value="胖子君"/>
</bean>
- autowire="byName"会自动在容器上下文中查找对应的bean id,即会根据
setDog
方法找到 dog对象 注意是小写,所以Dog的bean id要为dog(局限性太大了)
bytype
byName:会自动在容器上下文中查找,和自己对象属性的类型对应的bean id
bytype的时候,需要保证所有bean的class唯一, 并且这个bean需要和自动注入的属性的类型一致
<bean id="dog" class="com.Huiex.pojo.Dog"/>
<bean id="cat" class="com.Huiex.pojo.Cat"/>
<bean id="People" class="com.Huiex.pojo.People" autowire="byType">
<property name="name" value="胖子君"/>
</bean>
Bean作用域
单例模式
spring默认模式 同一对象在IOC容器中只有一个
scope="singleton"
设置 单例模式
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
<bean id="cat" class="com.Huiex.pojo.Cat" scope="singleton"/>----scope可省略
<bean id="cat22" class="com.Huiex.pojo.Cat"/>
测试体验:
@Test
public void peopleTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
Cat cat = context.getBean("cat", Cat.class);
Cat cat22 = context.getBean("cat22", Cat.class);
Cat cat33 = context.getBean("cat", Cat.class);
System.out.println(cat == cat22);--------false
System.out.println(cat == cat33);--------true 同一个对象(出自同一个bean),只是名字不同
}
原型模式
每次从容器中get的时候,都会产生一个新对象
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
其他
其余的request、session. application. 这些个只能在web开发中使用到
注解实现自动装配
1.配置文件
(官方文档)
<?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:context="http://www.springframework.org/schema/context"-------------这个
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context-----------------------这两个
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>------------------------------------------还有这个
</beans>
2.开启注解的支持
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/> ---------------<!--开启注解的支持-->
<bean id="Dog" class="com.Huiex.pojo.Dog"/>
<bean id="Cat" class="com.Huiex.pojo.Cat"/>
<bean id="People" class="com.Huiex.pojo.People"/>
</beans>
3.在属性上添加注解
@Autowired
(中文翻译 自动连线)
作用
自动装配已经在IOC容器里面的对象
-
直接在属性上使用即可,也可以在set方式上使用
-
Autowired注解是智能识别的
当注入容器存在多个同一类型的对象时,就是根据byName进行装配
当注入在IoC容器中该类型只有一个时,就通过byType进行装配
<!--开启注解的支持-->
<context:annotation-config/>
<bean id="dog" class="com.Huiex.pojo.Dog"/>
<bean id="cat" class="com.Huiex.pojo.Cat"/>
<bean id="People" class="com.Huiex.pojo.People"/>
在@Autowired注解下,会自动去IOC容器中寻找符合属性dog的byName的bean id
如果找不到符合的bean id 则寻找byType
@Data
public class People {
private String name;
@Autowired-------------------------------------------------------在属性上添加注解
private Dog dog;
@Autowired(required = false)--------------------------------设置这个对象,允许为空
private Cat cat;
}
属性
@Autowired(required = false)
如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
@Qualifier
@Qualifier(value=“xx”) 配和@Autowired的使用,指定一个唯一的bean对象注入
像以下这种情况,配置文件中创建了有两个Cat类型的cat对象,并且byName都不符合bean id
<bean id="cat33" class="com.Huiex.pojo.Cat"/>
<bean id="cat22" class="com.Huiex.pojo.Cat"/>
但是byType又一样,所以用@Qualifier(value = “cat22”)指定bean id (真好用,这个 )
public class People {
@Autowired(required = false)
@Qualifier(value = "cat22")
private Cat cat;
private String name;
@Autowired
private Dog dog;
}
没有可用的“com.Huiex.pojo.Cat”类型的合格 bean:预期单个匹配 bean,但发现 2:cat33,cat22
半注解开发
配置文件-组件扫描
指定要主描的包,这个包下的注解就会生效
<context:component-scan base-package="com.Huiex.pojo"/>
配置文件
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--指定要主描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.Huiex.pojo"/>
<!--开启注解的支持-->
<context:annotation-config/>
</beans>
自动装配bean
@Component组件,放在类上,说明这个类被Spring管理了,就是bean
表明一个类会作为组件类,并告知Spring要为这个类创建bean
@Data
@Component("user")--------------------相当于<bean id="user"class="com.Huiex.pojo.User">
public class User {
private String name = "胖子君";
}
属性注入
@Value
@Data
@Component("user")
public class User {
@Value("胖子君")-------------------------相当于<property name="name" value="胖子君"/>
private String name ;
}
衍生的注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
- dao -------------------@Repository
- service ---------------@Service
- controller------------@Controller
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean。
作用域
@Scope
@Data
@Component("user")
@Scope("singleton")---------------------------------------------开启单例模式(默认)
public class User {
@Value("胖子君")
private String name ;
}
对比
xml与注解
- xml更加万能,适用于任何场合!维护简单方便
- 注解不是自己类使用不了,维护相对复杂
xml与注解最佳实践
- xml用来管理bean;
- 注解只负责完成属性的注入;
完全注解开发
和半注解开发就一个区别,用了Config类代替了xml文件
JavaConfig
建立一个JavaConfig配置类 代替以下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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--指定要主描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.Huiex.pojo"/>
<!--开启注解的支持-->
<context:annotation-config/>
</beans>
配置类
配置类代替配置文件
@Configuration
@ComponentScan("com.Huiex.pojo")
public class Config {
}
}
@Configuration (汉译配置)
- 会被Spring容器托管,注册到容器中,因为他本来就是一 个@Component
- 代表这是一 个配置类,就和我们之前看的beans . xml
@ComponentScan
相当于配置文件中的 <context:component-scan base-package="com.Huiex.pojo"/>
自动装配bean
@Bean
可有可无@Bean 一般用来获取数据库连接池Connection这种对象
- 注册一个bean,就相当于bean标签
- @Bean(name =“ XX”) 中XX就相当于
bean
的``id` 默认为这个方法的名字, - 这个方法的返回值,就相当bean标签中的class属性
相当于<bean id="getStudent"class="com.Huiex.pojo.Student">
@Configuration
@ComponentScan("com.Huiex.pojo")
public class Config {
@Bean
public Student getStudent(){
return new Student();------------------------------就是返回要注入到bean的对象
}
}
- 这里自己的对象直接扫描就可以注入,@Bean一般用于外部第三方类对象注入,比如数据源
有了@bean没有@ComponenScan也行,,不过不建议,极其
属性注入
@Value
相当于<property name="name" value="胖子君"/>
@Data
@Component-----------------------------------------------自动装配bean
public class Student {
@Value("胖子君")--------------------------------------属性注入
private String name;
}
详细见上面的注解
创建对象
AnnotationConfigApplicationContext
如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig 上下文来获取,通过配置类的class对象加载
@Test
public void annotationTest(){
ApplicationContext context =
new AnnotationConfigApplicationContext(Config.class);
Student student = context.getBean("getStudent",Student.class);
System.out.println(student.toString());
}
配置类中的方法名就是bean id
@Configuration
@ComponentScan("com.Huiex.pojo")
public class Config {
@Bean
public Student getStudent(){
return new Student();------------------------------就是返回要注入到bean的对象
}
}
代理模式
静态代理
角色分析
- 抽象角色: 一般会使用接口或者抽象类来解决
//租房
public interface Rent {
public void rent();
}
- 真实角色: 被代理的角色
//房东
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子");
}
}
- 代理角色: 代理真实角色,代理真实角色后,我们一般会做一-些附属操作
//中介
public class Proxy(){
}
- 客户: 访问代理对象的人
/**租客*/
public class Client {
}
代理模式的好处
- 可以使真实角色的操作更加纯粹!不用去关注一 些公共的业务
- 公共也就就交给代理角色!实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
代理模式的缺点
- 一个真实角色就会产生一个代理角色;代码量会翻倍开发效率会变低
AOP实现机制
动态代理
-
动态代理和静态代理角色一样
-
动态代理的代理类是动态生成的,不是我们直接写好的
-
动态代理分为两大类:1.基于接口的动态代理,2.基于类的动态代理
- 基于接口:JDK动态代理
- 基于类: cglib
- java字节码实现:javasist
JDK动态代理
作用
有接口情况,使用JDK动态代理
创建接口实现类代理对象,增强类的方法。
newProxyInstance方法
使用Proxy类里面的newProxyInstance方法创建代理对象
方法有三个参数:
l 第一参数,当前类的加载器。
l 第二参数,增强方法所在的类 实现的 接口,支持多个接口。接口为class[ ]类型
l 第三参数,一个类的对象,该类实现InvocationHandler接口,在该类中创建代理对象,写增强的方法
JDK动态代理代码
CGLIB动态代理
l 没有接口情况,使用CGLIB动态代理
创建子类的代理对象,增强类的方法。
InvocationHandler是由代理实例的调用处理程序实现的接口。
每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时,方法调 用将被编码并分派到其调用处理程序的invoke方法。
面向切面编程
- 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得
业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
-
通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
-
使用登录例子说明AOP
术语
连接点
类里面哪些方法可以被增强,这些方法称为连接点
实际被真正增强的方法,称为切入点
通知(增强)
-
实际增强的逻辑部分称为通知(增强)
-
通知有多钟类型
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知 finally
切面
是动作
把通知应用到切入点过程
AOP
基于AspectJ实现AOP操作
- l 代替JDK动态代理
- l Spring框架一般都是基于Aspect实现AOP操作
- l AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spimg.框架依起使用,进行AOP操作。
1.导入依赖
pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
2.开启aop注解支持
在配置文件中开启aop注解支持 <aop:aspectj-autoproxy/>
<?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/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启aop注解支持-->
<aop:aspectj-autoproxy/>
</beans>
3.配置类
@Configuration
@ComponentScan(basePackages = {"com.Huiex"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Config {
}
@EnableAspectJAutoProxy(proxyTargetClass = true)开启拦截器,当用全注解实现AOP时,要配置
4.建立接口和要被增强的实现类
interface
public interface UserService {
public void add();
public void delete();
}
Impl
@Component---------------------------------------------------标注该类,生成该类的Beans对象
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加了一个add");
}
5.切面(代理)类
@Component
@Aspect//标注这个类是一个切面
public class PointCut {
@Before(value = "execution(* com.Huiex.service.UserServiceImpl.add(..))")
public void before(){
System.out.println("方法执行前");
}
}
- @Component标注该类,生成该类的Beans对象
- @Aspect 标注这个类是一个切面
- @Before(value = “execution(* com.Huiex.service.UserServiceImpl.add(…))”)设置切入的方法
6.Test2
public class MyTest {
@Test
public void test(){
ApplicationContext context =
new AnnotationConfigApplicationContext(Config.class);
UserService userService =
context.getBean("userServiceImpl", UserServiceImpl.class);
userService.add();
userService.delete();
}
}
结果
方法执行前
增加了一个add
删除了一个delete
切入点表达式
作用
设置对哪个类里面的哪个方法进行增强。
语法结构
execution ( [返回类型] 权限修饰符 [类全路径]. [方法名称] ( [参数列表] ) )
1.对com.atguigu.dao.BookDao类里面的add进行增强。
@Before(value = "execution(* com.Huiex.service.UserServiceImpl.add(..))")
返回类型所有 修饰符省略 类的全类名.方法名(..)参数用两点表示
2.对com.atguigu.dao.BookDao类里面的所有的方法进行增强。
@Before(value = "execution(* com.Huiex.service.UserServiceImpl.*(..))")
3.对com.atguigu.dao包里面所有类,类里面所有方法进行增强。
@Before(value = "execution(* com.Huiex.*.*.*(..))")
配置不同类型的通知
l 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
前置通知 @Before
@Before注解表示作为前置通知
最终通知 @After
@After(相当于finally)
后置通知 @AfterReturning
异常通知 @AfterThrowing
环绕通知 @Around
不同通知顺序
@Before 在增强方法前面
@Around 在最前和最后
@AfterReturning 在增强方法后面
@After 在增强方法后面 在@AfterReturning后面 一定会触发
@AfterThrowing 出现异常后触发此通知,增强方法后的只会触发@Afte通知