小码笔记20:Spring框架IoC、AOP

小码笔记SpringIoC

一、Spring步骤入门

  • Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(反转控制)和 AOP(面向切面编程)为内核。

  • 提供了展现层 SpringMVC和持久层 Spring JDBCTemplate以及业务层事务管理等众多的企业级应用技术。重配置轻代码

在这里插入图片描述

  • Spring程序开发步骤

    1. 导入坐标
    2. 创建Bean
    3. 创建applicationContext
    4. 在配置文件中配置 
    5. 创建ApplicationContext对象getBean
    
1.在Maven项目中的pom.xml中导入Spring坐标
<dependencies>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.7.RELEASE</version>
        </dependency>   
<dependencies>
2.编写Dao接口和实现类Bean
public interface UserDao {  
    public void save();
}

public class UserDaoImpl implements UserDao {  
    public void save() {
    System.out.println("UserDao save method running....");
  }
}
3.创建applicationContext
在类路径下(resources)创建Spring Config配置文件
推荐命名:applicationContext.xml
4.在Spring配置文件中配置UserDaoImpl
在applicationContext.xml中配置
<beans>
   <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
</beans>
5.使用Spring的API获得Bean实例
@test
public void test(){
    //1.加载配置文件 创建Spring容器
    ApplicationContext app = new  ClassPathXmlApplicationContext("applicationContext.xml");
    //2.通过app对象通过id获取对象
    UserDao userDao = (UserDao) app.getBean("userDao");            
    userDao.save();
 }
6.补充:ApplicationContext对象

pplicationContext:接口,代表应用上下文,可以通过其实例获得 Spring 容器中的 Bean 对象

  • 常见子类

    1. ClassPathXmlApplicationContext 
      从类的根路径下加载配置文件 推荐使用这种
    2. FileSystemXmlApplicationContext 
      从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
    3. AnnotationConfigApplicationContext
      当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
    
  • 常用方法

    1.Object  getBean(String str) 
      通过Java反射。根据Bean的id从容器中获得Bean实例,返回是Object,需要强转
    
    3.Object  getBean(Class xxx.class) //Bean唯一推荐用这个,其他时候用上面
    根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,此方法会报错
    

二、IoC:xml配置

1.Bean标签基本配置
  • id和class

    用于配置对象交由Spring 来创建。
    默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。
    基本属性:
    	id:Bean实例在Spring容器中的唯一标识
    	class:Bean的全限定名称
    
  • scope:指对象的作用范围,取值如下:
    |取值范围|说明|
    |-|-|
    |singleton|默认值,单例的|
    |prototype|多例的|

    1.当scope的取值为singleton时
      Bean的实例化个数:1个
      Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
      Bean的生命周期:
      对象创建:当应用加载,创建容器时,对象就被创建了
      对象运行:只要容器在,对象一直活着
      对象销毁:当应用卸载,销毁容器时,对象就被销毁了
    
    2.当scope的取值为prototype时
      Bean的实例化个数:多个
      Bean的实例化时机:当调用getBean()方法时实例化Bean
      对象创建:当使用对象时,创建新的对象实例
      对象运行:只要对象在使用中,就一直活着
      对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了
    
  • 3.Bean生命周期配置

    init-method:指定类中的初始化方法名称
    destroy-method:指定类中销毁方法名称
    
  • 4.引入其他配置文件(分模块开发)

    部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载
      <import resource="applicationContext-xxx.xml"/> 
    
2.Bean配置
1. 使用无参构造方法实例化(默认)
    配置文件配置
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/> 
    
2.工厂静态方法实例化
    工厂的静态方法返回Bean实例
     public class StaticFactoryBean {
        public static UserDao createUserDao(){    
        return new UserDaoImpl();
        }
    } 
    配置文件配置
    <bean id="userDao" class="com.itheima.factory.StaticFactoryBean" factory-method="createUserDao" /> 
    
3. 工厂实例方法实例化
    工厂的非静态方法返回Bean实例 
     public class DynamicFactoryBean {  
        public UserDao createUserDao(){        
          return new UserDaoImpl(); 
        }
    } 
    配置文件配置
    <bean id="factoryBean" class="com.itheima.factory.DynamicFactoryBean"/>
    <bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/> 
3.注入Bean

依赖注入(Dependency Injection):DI, Spring 核心 IOC 的具体实现。
通过控制反转,把对象的创建交给了 Spring,业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系让 Spring 来维护
总结:把持久层对象注入业务层,不用我们自己去获取

1.构造方法注入
    第一步:在UserServiceImpl中添加userDao属性
    第二步:在UserServiceImpl创建有参构造

    第三步:修改配置文件
        配置文件修改前
        <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
        配置文件修改后
        <bean id="userService" class="com.itheima.service.impl.UserServiceImpl">              
             <constructor-arg name="userDao" ref="userDao"></constructor-arg>
        </bean> 
        
2.set方法注入
    第一步:在UserServiceImpl中添加userDao属性
    第二步:在UserServiceImpl中添加setUserDao方法 
    第二步: 修改配置文件  
     配置文件修改前
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
     配置文件修改后
    <bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean> 
    
    set方法:P命名空间注入
        P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:
        首先,需要引入P命名空间:
        xmlns:p="http://www.springframework.org/schema/p" 
        其次,需要修改注入方式 
        <bean id="userService" class="com.itheima.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
4.注入Bean成员变量
  • 普通数据类型
    引用数据类型
    集合数据类型
    之前的操作都是对UserDao对象的引用进行注入的
1.普通数据类型的注入
    第一步:在UserServiceImpl中添加userDao属性
    第二步:在UserServiceImpl中添加setUserDao方法 
    第二步: 修改配置文件  
     <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
      <property name="company" value="传智播客"></property>
      <property name="age" value="15"></property>
    </bean>
     
2.集合数据类型(List<String>)的注入
    第一步:在UserServiceImpl中添加strList属性
    第二步:在UserServiceImpl中添加getStrList方法 
    第二步: 修改配置文件
    <--List<String>-->
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
        <property name="strList">
            <list>
                <value>aaa</value>
                <value>bbb</value>
                <value>ccc</value>
            </list>
        </property>
    </bean>
     <--List<User>--> 
     <bean id="u1" class="com.itheima.domain.User"/>
    <bean id="u2" class="com.itheima.domain.User"/>
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
        <property name="userList">
            <list>
                <bean class="com.itheima.domain.User"/>
                <bean class="com.itheima.domain.User"/>
                <ref bean="u1"/>
                <ref bean="u2"/>       
            </list>
        </property>
    </bean> 
     <--Map<String,User>--> 
     <bean id="u1" class="com.itheima.domain.User"/>
    <bean id="u2" class="com.itheima.domain.User"/>
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
        <property name="userMap">
            <map>            
                <entry key="user1" value-ref="u1"/>
                <entry key="user2" value-ref="u2"/>
            </map>
        </property>
    </bean>
    <--Properties-->
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
        <property name="properties">
            <props>
                <prop key="p1">aaa</prop>
                <prop key="p2">bbb</prop> 
                <prop key="p3">ccc</prop>
            </props>
        </property>
    </bean>  
5.Bean配置总结:
<bean>标签
  id属性:在容器中Bean实例的唯一标识,不允许重复
  class属性:要实例化的Bean的全限定名
  scope属性:Bean的作用范围,常用是Singleton(默认)和Prototype
  <property>标签:属性注入
        name属性:属性名称
        value属性:注入的普通属性值
        ref属性:注入的对象引用值
        <list>标签
        <map>标签
        <properties>标签
  <constructor-arg>标签
<import>标签:导入其他的Spring的分文件
6.Spring配置数据源
  • 可以将DataSource( 数据源 )的创建权交由Spring容器去完成
  • DataSource有无参构造方法,而Spring默认就是通过无参构造方法实例化对象的
  • DataSource要想使用需要通过set方法设置数据库连接信息,而Spring可以通过set方法进行字符串注入
1.创建数据源的配置文件 jdbc.properties
	jdbc.driver=com.mysql.jdbc.Driver
	jdbc.url=jdbc:mysql://localhost:3306/test
	jdbc.username=root
	jdbc.password=root
	
2.在Spring配置文件引入context命名空间和约束路径
	命名空间:xmlns:context="http://www.springframework.org/schema/context"
	约束路径:http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	
3.在Spring配置文件注入数据源(配置bean)
	//读取数据源的配置文件
	<context:property-placeholder location="classpath:jdbc.properties"/>
	//根据数据源配置文件获取信息注入bean
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
	    <property name="driverClass" value="${jdbc.driver}"/>
	    <property name="jdbcUrl" value="${jdbc.url}"/>
	    <property name="user" value="${jdbc.username}"/>
	    <property name="password" value="${jdbc.password}"/>
	</bean>

三、IoC:注解开发

1.Spring原始注解

Spring是轻代码而重配置的框架,注解代替xml配置文件可以简化配置,提高开发效率

注解说明
@Component使用在类上用于实例化Bean
@Controller使用在web层类上用于实例化Bean
@Service使用在service层类上用于实例化Bean
@Repository使用在dao层类上用于实例化Bean
@Autowired使用在字段上用于根据类型依赖注入
@Qualifier结合@Autowired一起使用用于根据名称进行依赖注入
@Resource相当于@Autowired+@Qualifier,按照名称进行注入
@Value注入普通属性
@Scope标注Bean的作用范围
@PostConstruct使用在方法上标注该方法是Bean的初始化方法
@PreDestroy使用在方法上标注该方法是Bean的销毁方法
  • 1.配置注解扫描(除非后面用@Configuration注解类配置)
    使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,告诉Spring你在何处使用了注解

    在Spring配置文件中配置注解扫描
    <!--注解的组件扫描-->
    <context:component-scan base-package="com.itheima"></context:component-scan>
    
2.注解Bean

使用@Compont或@Repository标识UserDaoImpl需要Spring进行实例化

1.//@Component("userDao")
@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
      System.out.println("save running... ...");
    }
}
3.注解成员变量
1.使用@Compont@Service标识UserServiceImpl需要Spring进行实例化
  使用@Autowired或者@Autowired+@Qulifier或者@Resource进行userDao的注入
//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService {
    /*@Autowired
    @Qualifier("userDao")*/
    @Resource(name="userDao")
    private UserDao userDao;
    @Override
    public void save() {       
       userDao.save();
    }
}
2.使用@Value进行字符串的注入
		@Repository("userDao")
	public class UserDaoImpl implements UserDao {
	    @Value("注入普通数据")
	    private String str;
	    @Value("${jdbc.driver}")
	    private String driver;
	    @Override
	    public void save() {
	        System.out.println(str);
	        System.out.println(driver);
	        System.out.println("save running... ...");
	    }
	}
4.注解Bean范围和初始化销毁方法
1.使用@Scope标注Bean的范围
//@Scope("prototype")
@Scope("singleton")
public class UserDaoImpl implements UserDao {
   //此处省略代码
}
2.使用@PostConstruct标注初始化方法,使用@PreDestroy标注销毁方法
@PostConstruct
public void init(){
  System.out.println("初始化方法....");
}
@PreDestroy
public void destroy(){
  System.out.println("销毁方法.....");
}
5.Spring新注解
  • 上面的注解还不能全部替代xml配置文件,需要引入新注解的配置

    注解说明
    @Configuration用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
    @ComponentScan用于指定 Spring 在初始化容器时要扫描的包。 作用和在 Spring 的 xml 配置文件中的 <context:component-scan base-package=“com.itheima”/>一样
    @Bean使用在方法上,标注将该方法的返回值存储到 Spring 容器中
    @PropertySource用于加载.properties 文件中的配置
    @Import用于导入其他配置类
6.注解Spring注解扫描
1.
新建一个Config包,SpringConfiguration类来写注解配置
	@Configuration //注解这是配置类
	@ComponentScan("com.itheima")  //开启注解扫描
	@Import({DataSourceConfiguration.class}) //引入数据源的配置类
	public class SpringConfiguration {
	}
	
2.数据源配置类DataSourceConfiguration
	@PropertySource("classpath:jdbc.properties")//加载数据源配置文件
	public class DataSourceConfiguration {
	    @Value("${jdbc.driver}")//注解基本类型的值
	    private String driver;
	    @Value("${jdbc.url}")
	    private String url;
	    @Value("${jdbc.username}")
	    private String username;
	    @Value("${jdbc.password}")
	    private String password;

3.数据源配置类里的数据源注解
	@Bean(name="dataSource")
	public DataSource getDataSource() throws PropertyVetoException { 
	    ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
	    dataSource.setDriverClass(driver);
	    dataSource.setJdbcUrl(url);
	    dataSource.setUser(username);
	    dataSource.setPassword(password);
	    return dataSource;
	}
	
4.测试类加载核心配置类创建Spring容器
	@Test
	public void testAnnoConfiguration() throws Exception {
	ApplicationContext applicationContext = new 
	        AnnotationConfigApplicationContext(SpringConfiguration.class);    
	    UserService userService = (UserService)    
	    applicationContext.getBean("userService");
	    userService.save();
	    DataSource dataSource = (DataSource) 
	    applicationContext.getBean("dataSource");
	    Connection connection = dataSource.getConnection(); 
	    System.out.println(connection);
	    }

四、Spring整合Junit(测试)

3.1 原始Junit测试Spring的问题

让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
将需要进行测试Bean直接在测试类中进行注入

Spring集成Junit步骤
1.导入spring集成Junit的坐标(原本Junit坐标也需要)
2.使用@Runwith注解替换原来的运行期
3.使用@ContextConfiguration指定配置文件或配置类
4.使用@Autowired注入需要测试的对象
5.创建测试方法进行测试
1.导入spring集成Junit的坐标
<!--此处需要注意的是,spring5 及以上版本要求 junit 的版本必须是 4.12 及以上-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
2.使用测试类的注解

@Runwith注解替换原来的运行期
@ContextConfiguration指定配置文件或配置类

//加载SpringJUnit让Spring知道这是测试类
@RunWith(SpringJUnit4ClassRunner.class)
//加载spring核心配置文件
//加载spring核心配置类
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {
}
3.注解需要测试的对象和测试方法

使用@Autowired注入需要测试的对象
创建测试方法进行测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})public class SpringJunitTest {
    @Autowired //标明需要测试的Bean
    private UserService userService;
    @Test
    public void testUserService(){
      userService.save();
    }
}

五、AOP:面向切面编程

  • AOP ( Aspect Oriented Programming ),面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。在程序运行期间,在不修改源码的情况下对方法进行功能增强
  • AOP是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,
    使得业务逻辑各部分降低耦合度,提高重用性,提高开发效率
1.AOP 的底层实现
  • AOP 的底层是通过 Spring 提供的的动态代理技术实现的。
  • 在运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调用目标对象的方法,从而完成功能的增强。
  • 常用的动态代理技术
    JDK 代理 : 基于接口的动态代理技术
    cglib 代理:基于父类的动态代理技术
    在这里插入图片描述
2. JDK 的动态代理(了解)

详细了解请查看厚者居上的博客Java JDK动态代理实现原理

1.目标类接口TargetInterface
    public interface TargetInterface {
        public void method();
    }
    
2.目标类Target 
    public class Target implements TargetInterface {
        @Override
        public void method() {
            System.out.println("Target running....");
        }
    }
     
3.测试类里动态代理代码 
    Target target = new Target(); //创建目标对象
    //创建代理对象
    TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    target.getClass().getInterfaces(),
    new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) 
                throws Throwable {
                    System.out.println("前置增强代码...");
                    Object invoke = method.invoke(target, args);
                    System.out.println("后置增强代码...");
                    return invoke;
                }
            }
    ); 
    
4.调用代理对象的方法测试 
    // 测试,当调用接口的任何方法时,代理对象的代码都无序修改
    proxy.method(); 

在这里插入图片描述

3.cglib 的动态代理(不需要接口,了解)
1.目标类
     public class Target {
        public void method() {
            System.out.println("Target running....");
        }
    } 
    
2. 动态代理代码
    Target target = new Target(); //创建目标对象
    Enhancer enhancer = new Enhancer();   //创建增强器
    enhancer.setSuperclass(Target.class); //设置父类
    enhancer.setCallback(new MethodInterceptor() { //设置回调
        @Override
        public Object intercept(Object o, Method method, Object[] objects, 
        MethodProxy methodProxy) throws Throwable {
            System.out.println("前置代码增强....");
            Object invoke = method.invoke(target, objects);
            System.out.println("后置代码增强....");
            return invoke;
        }
    });
    Target proxy = (Target) enhancer.create(); //创建代理对象 
    
3.调用代理对象的方法测试 
    //测试,当调用接口的任何方法时,代理对象的代码都无序修改
    proxy.method(); 

在这里插入图片描述

4.SpringAOP术语介绍
  • Spring 的 AOP 实现底层就是对上面的动态代理的代码进行了封装,
    封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定目标的方法增强。
    常用的术语和白话意思如下:

    1. Target(目标对象):代理的目标对象
    2. Proxy (代理):被增强后产生的一个结果代理类
    3. Joinpoint(连接点):可以被增强的方法
    4. Pointcut(切入点):选定被增强的的方法
    5. Advice(通知/ 增强):用来增强切入点的方法
    6. Aspect(切面):切入点+通知(引介)
    7. Weaving(织入):切点和增强结合的过程
    
5.AOP 开发需要做的事
1.需要编写的内容
      1.编写核心业务代码(目标类的目标方法)
      2.编写切面类,切面类中有通知(增强功能方法)
      3.在配置文件中,配置织入关系,即将哪些通知与哪些连接点进行结合

2.AOP 技术实现的内容
    Spring 框架监控切入点方法的执行。一旦监控到切入点方法被运行,使用代理机制,
    动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行。
    
3.AOP 底层使用哪种代理方式
    spring会根据目标类是否实现了接口来决定采用哪种动态代理的方式。

六、AOP:xml配置

步骤
  1. 导入 AOP 相关坐标
  2. 创建目标接口和目标类(内部有切点)
  3. 创建切面类(内部有增强方法)
  4. 将目标类和切面类的对象创建权交给 spring
  5. 在 applicationContext.xml 中配置织入关系
  6. 测试代码
1.导入 AOP 相关坐标
<!--导入spring的context坐标,context依赖aop-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.0.5.RELEASE</version>
</dependency>
<!-- aspectj的织入 -->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.13</version>
</dependency>
2.创建目标接口和目标类(内部有切点)
public interface TargetInterface {
    public void method();
}

public class Target implements TargetInterface {
    @Override
    public void method() {
        System.out.println("Target running....");
    }
}
3.创建切面类(内部有增强方法)
public class MyAspect {
    //前置增强方法
    public void before(){
        System.out.println("前置代码增强.....");
    }
}
4.将目标类和切面类的对象创建权交给 spring
<!--在Spring配置目标类-->
<bean id="target" class="com.itheima.aop.Target"></bean>
<!--配置切面类-->
<bean id="myAspect" class="com.itheima.aop.MyAspect"></bean>
5.配置织入关系
1.导入aop命名空间
<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/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
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
        
2.配置切点表达式和前置增强的织入关系
      <aop:config>
          <!--引用myAspect的Bean为切面对象-->
          <aop:aspect ref="myAspect">
              <!--配置Target的method方法执行时要进行myAspect的before方法前置增强-->
              <aop:before method="before" pointcut="execution(public void com.itheima.aop.Target.method())"></aop:before>
          </aop:aspect>
      </aop:config>
6.测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
    @Autowired
    private TargetInterface target;
    @Test
    public void test1(){
        target.method();
    }
}

在这里插入图片描述

7.注意事项:XML 配置要点
1.表达式语法:
	execution([修饰符] 返回值类型 包名.类名.方法名(参数))

2. 访问修饰符可以省略
      1.返回值类型、包名、类名、方法名可以使用星号*  代表任意      
      2.包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类     
      3. 参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表 
      
3.举例  
      execution(public void com.itheima.aop.Target.method())  
      execution(void com.itheima.aop.Target.*(..))
      execution(* com.itheima.aop.*.*(..))
      execution(* com.itheima.aop..*.*(..))
      execution(* *..*.*(..)) 
      
4.切点表达式的抽取
	当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 pointcut-ref 属性代替 pointcut 属性来引用抽取后的切点表达式。
	    <aop:config>
	        <!--引用myAspect的Bean为切面对象-->
	        <aop:aspect ref="myAspect">
	            <aop:pointcut id="myPointcut" expression="execution(* com.itheima.aop.*.*(..))"/>
	            <aop:before method="before" pointcut-ref="myPointcut"></aop:before>
	        </aop:aspect>
	    </aop:config>
	    
5.通知的类型
	<aop:通知类型 method=“切面类中方法名” pointcut=“切点表达式"></aop:通知类型>

在这里插入图片描述

  • XML配置AOP总结

    1.aop织入的配置
      <aop:config>
          <aop:aspect ref=“切面类”>
              <aop:before method=“通知方法名称” pointcut=“切点表达式"></aop:before>
          </aop:aspect>
      </aop:config> 
      
    2.切点表达式的写法:
       execution([修饰符] 返回值类型 包名.类名.方法名(参数))
    

七、AOP:注解开发

步骤
基于注解的aop开发步骤:
1.创建目标接口和目标类(内部有切点)

2.创建切面类(内部有增强方法)

3.将目标类和切面类的对象创建权交给 spring

4.在切面类中使用注解配置织入关系

5.在配置文件中开启组件扫描和 AOP 的自动代理

6.测试
1.创建目标接口和目标类(内部有切点)
public interface TargetInterface {
    public void method();
}

public class Target implements TargetInterface {
    @Override
    public void method() {
        System.out.println("Target running....");
    }
}
2.创建切面类(内部有增强方法)
public class MyAspect {
    //前置增强方法
    public void before(){
        System.out.println("前置代码增强.....");
    }
}
3.将目标类和切面类的对象创建权交给 spring
@Component("target")
public class Target implements TargetInterface {
    @Override
    public void method() {
        System.out.println("Target running....");
    }
}
@Component("myAspect")
public class MyAspect {
    public void before(){
        System.out.println("前置代码增强.....");
    }
}
4.在切面类中使用注解配置织入关系
@Component("myAspect")
@Aspect
public class MyAspect {
    @Before("execution(* com.itheima.aop.*.*(..))")
    public void before(){
        System.out.println("前置代码增强.....");
    }
}
5.在配置文件中开启组件扫描和 AOP 的自动代理
<!--组件扫描-->
<context:component-scan base-package="com.itheima.aop"/>

<!--aop的自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
6.测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
    @Autowired
    private TargetInterface target;
    @Test
    public void test1(){
        target.method();
    }
}

在这里插入图片描述

7.注意事项:注解配置要点

在这里插入图片描述

1.注解通知的类型
	通知的配置语法:@通知注解(“切点表达式")
2.切点表达式的抽取
	同 xml配置aop 一样,我们可以将切点表达式抽取。抽取方式是在切面内定义方法,
	在该方法上使用@Pointcut注解定义切点表达式,然后在在增强注解中进行引用。具体如下:
	
	@@Component("myAspect")
	@Aspect
	public class MyAspect {
	    @Before("MyAspect.myPoint()")
	    public void before(){
	        System.out.println("前置代码增强.....");
	    }
	    @Pointcut("execution(* com.itheima.aop.*.*(..))")
	    public void myPoint(){}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码为海

你的支持是我更新最大得动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值