ioc操作Bean管理
==========2022.6.1=
一、基于xml方式
FactoryBean
1.Spring有两种类型bean,一种普通bean,另一种工厂bean(FactoryBean)
2.普通bean:在spring配置文件中定义bean类型就是返回类型
3.工厂bean:在spring配置文件定义bean类型和返回类型不一样
第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步 实现接口里边的方法,在实现的方法中定义返回的bean类型
package com.yupei.spring5.factorybean;
import com.yupei.spring5.collectiontype.Course;
import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean<Course> {
//定义返回bean,,这里默认返回的是object
/*
* @Override
public Object getObject() throws Exception {
return null;
}
* */
@Override
public Course getObject() throws Exception {
Course course=new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
//是否是个单例
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
@Test
public void test3(){
ApplicationContext context=
new ClassPathXmlApplicationContext("bean7.xml");
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
<?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.xsd">
<bean id="myBean" class="com.yupei.spring5.factorybean.MyBean"></bean>
</beans>
bean作用域
1.在spring里边,设置创建bean实例是单实例还是多实例。
2.在spring里边,默认情况下,bean是单实例对象
3.如何设置单实例还是多实例
(1)在spring配置文件bean标签里边有属性scope用于设置单实例还是多实例
(2)scope属性值
第一个值 默认值,singleton,表示单实例对象
第二个值 prototype,表示是多实例对象
第三个值 request(不常用)
第四个值 session(不常用)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K4p42XWn-1654387589288)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220601193144376.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hl7u5hRC-1654387589289)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220601193214506.png)]
(3)singleton和prototype区别
第一 singleton单实例,prototype多实例
第二 设置scope的值是singleton时,加载spring配置文件时候就会创建单实例对象
设置scope的值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法时创建多实例对象
bean生命周期
1.生命周期
(1)从对象创建到对象销毁的过程
2.bean生命周期
(1)通过构造器创建bean实例(执行无参构造)
(2)为bean的属性设置值和对其他bean引用(调用set方法)
(3)调用bean的初始化的方法(需要进行配置初始化的方法)
(4)ban可以使用了(对象获取到了)
(5)当容器关闭时候,调用bean的销毁方法(需要进行配置销毁方法)
3.演示bean生命周期
package com.yupei.spring5.bean2;
public class Orders {
private String oname;
public Orders() {
System.out.println("第一步 执行无参构造创建bean实例");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 调用set方法设置属性的值");
}
//创建执行初始化的方法
public void initMethod(){
System.out.println("第三步 执行初始化方法");
}
//创建执行销毁的方法
public void destoryMethod(){
System.out.println("第五步 执行销毁方法");
}
}
@Test
public void testBean4(){
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("bean8.xml");
Orders orders = context.getBean("order", Orders.class);
System.out.println("第四步 获取创建bean实例对象");
System.out.println(orders);
//手动让bean实例销毁
context.close();
}
<?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.xsd">
<bean id="order" class="com.yupei.spring5.bean2.Orders" init-method="initMethod" destroy-method="destoryMethod" >
<property name="oname" value="shouji"></property>
</bean>
</beans>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-end2Cd4s-1654387589291)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220601221943132.png)]
4.bean的后置处理器(完整bean生命周期七步走)
(1)通过构造器创建bean实例(执行无参构造)
(2)为bean的属性设置值和对其他bean引用(调用set方法)
(3)把bean实例传递给bean后置处理器的方法postProcessBeforeInitialization
(4)调用bean的初始化的方法(需要进行配置初始化的方法)
(5)把bean实例传递给bean后置处理器的方法postProcessAfterInitialization
(6)ban可以使用了(对象获取到了)
(7)当容器关闭时候,调用bean的销毁方法(需要进行配置销毁方法)
5.演示添加后置处理器的效果
(1)创建一个类,实现接口BeanPostProcessor
package com.yupei.spring5.bean2;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在我们的初始化之前执行的方法");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在我们的初始化之后执行的方法");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
<?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.xsd">
<bean id="order" class="com.yupei.spring5.bean2.Orders" init-method="initMethod" destroy-method="destoryMethod" >
<property name="oname" value="shouji"></property>
</bean>
<!-- 配置后置处理器 配置完之后会为当前文件中所有bean实例添加后置处理器-->
<bean id="myBeanPost" class="com.yupei.spring5.bean2.MyBeanPost"></bean>
</beans>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b6ipypEu-1654387589293)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220601223544974.png)]
xml自动装配
1.什么是自动装配
(1)根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值注入
2.演示自动装配过程
(1)byName:根据属性名称注入,注入值bean的id值和类属性名称要一样
(2) byType:根据属性类型注入
<?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.xsd">
<!--实现自动装配
bean标签属性autowire,配置自动装配
autowire属性常用的两个值:byName:根据属性名称注入,注入值bean的id值和类属性名称要一样
byType:根据属性类型注入
-->
<bean id="dept" class="com.yupei.spring5.autowire.Dept"></bean>
<bean id="emp" class="com.yupei.spring5.autowire.Emp" autowire="byName">
<!-- <property name="dept" ref="dept"></property>-->
</bean>
</beans>
@Test
public void test5(){
ApplicationContext context=
new ClassPathXmlApplicationContext("bean9.xml");
Emp emp = context.getBean("emp", Emp.class);
System.out.println(emp);
emp.test();
}
package com.yupei.spring5.autowire;
public class Emp {
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"dept=" + dept +
'}';
}
public void test(){
System.out.println(dept);
}
}
package com.yupei.spring5.autowire;
public class Dept {
@Override
public String toString() {
return "Dept{}";
}
}
=2022.6.2==
引入外部属性文件
1.直接配置数据库信息(以数据库为例)
(1)配置德鲁伊连接池
(2)引入德鲁伊连接池jar包
<?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.xsd">
<!--直接配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql//localhost:3306/userDb"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
</beans>
2.引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties格式文件,写数据库信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8VPYb9pg-1654387589295)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220602094704417.png)]
(2)把外部properties属性文件引入spring配置文件中
引入context名称空间
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<!--注意要对名称空间做一个引入-->
在spring配置文件中使用标签引入外部属性文件
<!--先引入外部属性文件 属性文件在src下-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!-- 配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
二、基于注解方式
1.什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值,…)
(2)使用注解,注解作用在类上边,方法上边,属性上边
(3)使用注解目的:简化xml配置
2.Spring针对Bean管理中创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
上边的四个注解功能是一样的,都可以用来创建bean实例
3.基于注解方式实现对象创建
第一步 引入依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ONc5tL6N-1654387589298)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220602114417873.png)]
第二步 开启组件扫描
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启组件扫描
1.如果扫描多个包,多个包使用逗号隔开
base-package="com.yupei.spring5.dao,com.yupei.spring5.service"
2.扫描包上层目录 base-package="com.yupei.spring5"
-->
<context:component-scan base-package="com.yupei.spring5"></context:component-scan>
</beans>
第三步 创建类,在类上边添加创建对象的注解
package com.yupei.spring5.service;
import org.springframework.stereotype.Component;
//在注解里边value属性值可以省略不写,
//默认值是类名称,首字母小写
@Component(value = "userService") //<bean id="userService" class=".."/>
public class UserService {
public void add(){
System.out.println("service add..........");
}
}
测试:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fKiDoBpr-1654387589301)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220602122156138.png)]
4.开启组件扫描细节配置
<!--示例1
use-default-filters="false 表示现在不使用默认filter(默认filter扫描全部内容),自己配置filter
context:include-filter,设置扫描哪些内容
-->
<context:component-scan base-package="com.yupei.spring5" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例2
下面配置扫描全部内容
context:exclude-filter:设置那些内容不进行扫描
-->
<context:component-scan base-package="com.yupei.spring5">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
5.基于注解方式实现属性注入
(1)@AutoWired:根据属性类型进行自动装配
第一步:把dao和service对象进行创建,在service和dao类添加创建对象的注解
第二步:在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解@AutoWired
package com.yupei.spring5.service;
import com.yupei.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//在注解里边value属性值可以省略不写,
//默认值是类名称,首字母小写
@Service(value = "userService") //<bean id="userService" class=".."/>
public class UserService {
//定义dao类型属性
//不需要添加set方法了,添加注入属性注解就行了
@Autowired //根据类型进行注入
private UserDao userDao;
public void add(){
System.out.println("service add..........");
}
}
(2)@Qualifier:根据属性名称进行注入
这个@Qualifier注解的使用,和上边@AutoWired一起使用
//在注解里边value属性值可以省略不写,
//默认值是类名称,首字母小写
@Service(value = "userService") //<bean id="userService" class=".."/>
public class UserService {
//定义dao类型属性
//不需要添加set方法了,添加注入属性注解就行了
@Autowired//根据类型进行注入,如果该类型有多个实现类对象,那就不好办了。。。得用下边的注解,精准打击!
@Qualifier(value = "userDaoImpl1") //根据名称注入
private UserDao userDao;
public void add(){
System.out.println("service add..........");
userDao.add();
}
}
package com.yupei.spring5.dao;
import org.springframework.stereotype.Repository;
@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao{
@Override
public void add() {
System.out.println("dao add......");
}
}
(3)@Resource:可以根据类型注入,可以根据名称注入
//@Resource //根据类型进行注入
@Resource(name = "userDaoImpl1") //根据名称进行注入
private UserDao userDao;
public void add(){
System.out.println("service add..........");
userDao.add();
}
以上三个都是注入对象类型属性
(4)@Value:注入普通类型属性注入
@Value(value = "abc")
private String name;
6.完全注解开发
(1)创建配置类,替代xml配置文件
package com.yupei.spring5.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //作为配置类,替代xml文件
@ComponentScan(basePackages = {"com.yupei.spring5"})
public class SpringConfig {
}
(2)编写测试类
@Test
public void testService2(){
//加载配置类
ApplicationContext context
=new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
AOP(概念)
1.什么是AOP
(1)面向切面编程(方面),利用AOP可以对业务逻辑得各个部分进行隔离,从而使得业务逻辑各部分之间耦合度降低,提高程序的可重用性,同时提高了开发的效率
(2)通俗描述:不通过修改源代码方式,在主干功能里边添加功能
(3)使用登陆例子说明AOP
AOP(底层原理)
1.AOP底层使用动态代理
(1)有两种情况动态代理
第一种 有接口情况,使用JDK动态代理
*
创建接口实现类代理对象,增强类的方法
第二种 没有接口情况,使用CGLIB动态代理
*
创建子类的代理对象,增强类的方法
AOP(JDK动态代理)
1.使用JDK动态代理,使用Proxy类里边的方法创建对象(这个类在java.lang.reflect包中)
(1)调用newProxtyInstance方法(这是静态的,我们可以直接用类名.方法名去调用)
方法里边有三个参数
第一个参数:类加载器
第二个参数:增强方法所在的类,这个类实现的接口,支持多个接口
第三个参数:实现这个接口InvocationHandler,创建代理对象,写增强方法
2.编写JDK动态代理代码(要做的是通过动态代理把add()和update()方法的功能做增强…)
(1)创建接口,定义方法
package com.yupei.spring5;
public interface UserDao {
public int add(int a, int b);
public String update(String id);
}
(2)创建接口实现类,实现方法
package com.yupei.spring5;
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String update(String id) {
return id;
}
}
(3)使用Proxy类创建接口代理对象
package com.yupei.spring5;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
Class[] interfaces={UserDao.class};
// Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// });
UserDaoImpl userDao=new UserDaoImpl();
//类加载器 要增强方法所在类实现的接口名
UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int result = dao.add(1, 2);
System.out.println(result);
}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
//1.把创建的是谁(这里是UserDaoImpl)的代理对象,把谁传递过来
//通过有参数构造传递
private Object obj;
public UserDaoProxy(Object obj){
this.obj=obj;
}
//增强的逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("在方法之前执行..........."+method.getName()+":传递的参数.."+ Arrays.toString(args));
//被增强的方法执行
Object res = method.invoke(obj, args);
//方法之后
System.out.println("方法之后执行..."+obj);
return res;
}
}
AOP(术语)
1.连接点
类里边的哪些方法可以被增强,这些方法称为连接点
2.切入点
实际被真正增强的方法,称为切入点
3.通知(增强)
(1)实际增强的逻辑部分称为通知(增强)
(2)通知有多种类型
*前置通知
*后置通知
*环绕通知
*异常通知
*最终通知
4.切面
是动作
(1)把通知应用到切入点的过程
AOP操作(准备工作)
1.Spring框架一般基于AspectJ实现AOP操作
(1)什么是AspectJ
*AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和spring框架一起使用,进行AOP操作
2.基于AspectJ实现AOP操作
(1)基于xml配置文件实现
(2)基于注解方式实现(使用)
3.在项目工程里边引入AOP相关依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hi1s6TyU-1654387589315)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220604081315103.png)]
4.切入点表达式
(1)切入点表达式作用:知道对哪个了类里边的哪个方法进行增强
(2)语法结构:
execution([权限修饰符] [返回类型] [类全路径] [ 方法名称] [参数名称])
注:权限修饰符可以省略,下边的都省略了,*代表任意
举例1:对com.yupei.dao.BookDao类里边的add进行增强
execution(*
com.yupei.dao.BookDao.add(…))
举例2:对com.yupei.dao.BookDao类里边所有的方法进行增强
execution(*
com.yupei.dao.BookDao.*
(…))
举例3:对com.yupei.dao包里边所有类,类里边所有方法进行增强
execution(*
com.yupei.dao.*
.*
(…))
AOP操作(AspectJ注解)
1.创建类,在类里边定义方法(一会要去实现对类中的方法进行增强,此类就是被增强类)
package com.yupei.spring5.aopanno;
public class User {
public void add(){
System.out.println("add.........");
}
}
2.创建增强类(编写增强逻辑)
(1)在增强类里边,创建方法,让不同方法代表不同通知类型
package com.yupei.spring5.aopanno;
//增强的类
public class UserPorxy {
//前置通知
public void before(){
System.out.println("before.....");
}
}
3.进行通知的配置
(1)在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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置文件中需要用到一些相关的名称空间 ,我们先添加一下,以上-->
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.yupei.spring5.aopanno"></context:component-scan>
</beans>
(2)使用注解创建User和UserProxy对象
package com.yupei.spring5.aopanno;
import org.springframework.stereotype.Component;
//增强的类
@Component
public class UserPorxy {
//前置通知
public void before(){
System.out.println("before.....");
}
}
package com.yupei.spring5.aopanno;
import org.springframework.stereotype.Component;
//被增强的类
@Component
public class User {
public void add(){
System.out.println("add.........");
}
}
(3)在增强类上边添加注解@Aspect(他就是表示让这个类生成一个代理对象)
package com.yupei.spring5.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
//增强的类
@Component //注解创建对象
@Aspect //注解生成代理对象
public class UserPorxy {
//前置通知
public void before(){
System.out.println("before.....");
}
}
(4)在spring配置文件中开启生成代理对象
<!--开启Aspect生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
4.配置不同类型通知
(1)在增强类的里边,在作为通知方法上边添加通知类型注解,使用切入点表达式配置。
package com.yupei.spring5.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//增强的类
@Component //注解创建对象
@Aspect //注解生成代理对象
public class UserPorxy {
//前置通知
@Before(value = "execution(* com.yupei.spring5.aopanno.User.add(..))")
public void before(){
System.out.println("before.....");
}
//最终通知 after表示方法之后就执行,有异常也会执行
@After(value ="execution(* com.yupei.spring5.aopanno.User.add(..))")
public void after(){
System.out.println("after...........");
}
//后置通知(返回通知) AfterReturning表示在返回结果后执行,有异常就不执行了
@AfterReturning(value ="execution(* com.yupei.spring5.aopanno.User.add(..))")
public void AfterReturning(){
System.out.println("AfterReturning...........");
}
//异常通知 有异常才会执行
@AfterThrowing(value ="execution(* com.yupei.spring5.aopanno.User.add(..))")
public void AfterThrowing(){
System.out.println("AfterThrowing...........");
}
//环绕通知
@Around(value ="execution(* com.yupei.spring5.aopanno.User.add(..))")
public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前...........");
//倍增前的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后...........");
}
}
5.公共切入点抽取
package com.yupei.spring5.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//增强的类
@Component //注解创建对象
@Aspect //注解生成代理对象
public class UserPorxy {
//相同切入点抽取
@Pointcut(value = "execution(* com.yupei.spring5.aopanno.User.add(..))")
public void pointdemo(){
}
//前置通知
@Before(value = "pointdemo()")
public void before(){
System.out.println("before.....");
}
//最终通知
@After(value ="pointdemo()")
public void after(){
System.out.println("after...........");
}
//后置通知(返回通知)
@AfterReturning(value ="pointdemo()")
public void AfterReturning(){
System.out.println("AfterReturning...........");
}
//异常通知
@AfterThrowing(value ="pointdemo()")
public void AfterThrowing(){
System.out.println("AfterThrowing...........");
}
//环绕通知
@Around(value ="pointdemo()")
public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前...........");
//倍增前的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后...........");
}
}
6.有多个增强类对同一个方法进行增强,设置增强类优先级
(1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高 ,值从0开始
package com.yupei.spring5.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component //创建增强类对象
@Aspect //生成增强类的代理对象
@Order(1) //有多个增强类时,设置增强类的优先级 值越小优先级越高
public class PersonProxy {
//相同切入点抽取
@Pointcut(value = "execution(* com.yupei.spring5.aopanno.User.add(..))")
public void pointdemo(){
}
//前置通知
@Before(value = "pointdemo()")
public void before(){
System.out.println("Person before.....");
}
}
7.完全使用注解开发
(1)创建配置类,不需要创建xml配置文件
package com.yupei.spring5.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration //定义此类是注解工具类
@ComponentScan(basePackages = "com.yupei.spring5") //开启注解扫描
@EnableAspectJAutoProxy(proxyTargetClass = true) //生成代理对象
public class ConfigAop {
}
AOP操作(AspectJ配置文件, 了解即可)
1.创建两个类,增强类和被增强类,创建方法
package com.yupei.spring5.aopxml;
//增强类
public class BookProxy {
public void before(){
System.out.println("before.......");
}
}
----------------------------
package com.yupei.spring5.aopxml;
//被增强类
public class Book {
public void buy(){
System.out.println("buy..........");
}
}
2.在spring配置文件中创建两个类对象
<!-- 创建两个类的对象-->
<bean id="book" class="com.yupei.spring5.aopxml.Book"></bean>
<bean id="bookProxy" class="com.yupei.spring5.aopxml.BookProxy"></bean>
</beans>
3.在spring配置文件中配置切入点
<!--配置aop增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* com.yupei.spring5.aopxml.Book.buy(..))"/>
<!--配置切面 -->
<aop:aspect ref="bookProxy">
<!--配置增强作用在具体方法上-->
<aop:before method="before" pointcut-ref="p"></aop:before>
</aop:aspect>
</aop:config>