Spring核心容器——从配置文件到注解开发 创建对象+成员变量赋值 增强方法

news2024/11/15 7:22:05

目录

  • 引出
  • Spring入门案例
    • 初识Spring
    • 入门案例1----用配置文件实现 Druid + JDBCTemplate + dao
      • 1.之前的方式:new对象
      • 2.用配置文件的方法把new对象交给Spring
      • 3.如果要用对象,从spring的容器中获取ac.getBean("userDao");
      • 4.实体类和dao层的代码--问题:如果接口有两个实现类?
      • 【补充】获取spring容器中对象的两种方式:id 或 对象类型
    • 入门案例2----person实体类对配置文件理解
      • (1)初始情况:当spring程序读到这一行时,就创建了一个person类,放到spring的容器中,其id为person;
      • (2)参数scope="singleton"单例、scope="prototype"非单例:
      • (3)给成员变量赋值的方式 + 依赖注入
      • (4)测试文件执行顺序,new spring容器--读取bean.xml文件...
  • Spring新建对象+给成员变量赋值—从配置文件到注解开发
    • 用配置文件实现controller≈servlet
      • 1.导包--用spring.verson实现版本控制
      • 2.配置文件编写applicationContext.xml
      • 3.进行测试ClassPathXmlApplicationContext
    • 用注解的方式实现controller
      • 1.配置文件xml的更新context:component-scan
      • 2.在dao,service,controller上标注注解@Component(@Repository @Service @Controller) + @Autowired
      • 3.进行测试ClassPathXmlApplicationContext
    • 用SpringConfig.java文件代替resource下的xml配置文件
      • 3.用SpringConfig.java文件代替resource下的xml配置文件 @Configuration @ComponentScan @Bean
      • 4.进行测试AnnotationConfigApplicationContext
    • SpringCofig.java文件引入properties文件---解耦druid + 引入其他config.java
      • 1.引入jdbc.properties配置文件@PropertySource("classpath:jdbc.properties")+@Value("${jdbc.url}")
      • 2.引入其他的config.java文件@Import(SpringConfig.class)
    • 配置单例/多例,初始化化方法,销毁方法
      • 1.@Scope(value = "singleton") prototype + @PostConstruct + @PreDestroy
      • 2.配置文件@Configuration @ComponentScan("com.tianju") + 测试AnnotationConfigApplicationContext
    • 如果一个接口有两个实现类---入门案例的问题
      • 1.方案一:指定名字---指定其中的一个实现类userServiceImpl
      • 2.方案二:用注解 @Qualifier("userServiceImp2") 进行指定 + @Autowired
      • 3.方案三:用一个注解@Resource(name = "userServiceImpl")替换上面的两个
  • Spring增强方法——给一批类全部做增强
    • 用配置文件做增强
      • 1.增强类LogActiveDemo.java文件
      • 2.被增强的类UserController.java文件
      • 3.进行增强与被增强的配置
      • 4.测试用例及其结果ClassPathXmlApplicationContext("beans.xml");
    • 用注解做增强
      • 1.增强类LogActiveDemo.java文件 @Aspect,(@Before("execution(* com.tianju.controller.UserController.*(..))"), @After, @AfterReturning, @AfterThrowing)
      • 2.自定义注解MyAnnoClass.java文件@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME)
      • 3.被增强的类UserController.java文件@MyAnnoClass
      • 4.配置文件SpringConfig.java文件开启动态代理 @EnableAspectJAutoProxy
      • 5.测试用例AnnotationConfigApplicationContext(SpringConfig.class);
    • 简化:从 @Before("execution(* com.tianju.controller.UserController.*(..))") 到@After("@annotation(com.tianju.anno.MyAnnoMethod)")
      • 1.自定义注解MyAnnoMethod.java文件@Target({ElementType.METHOD})
      • 2.增强类LoginActiveAnnoMethod.java文件@Before("@annotation(com.tianju.anno.MyAnnoMethod)")
      • 3.被增强类OpusController.java文件@MyAnnoMethod
      • 4.配置文件SpringConfig.java文件开启动态代理 @EnableAspectJAutoProxy
      • 5.测试AnnotationConfigApplicationContext(SpringConfig.class)
    • 另一种方式:@Before("@within(org.springframework.stereotype.Controller)") + 日志的案例
      • 1.定义一个增强方法,标注@within
      • 2.正常写controller的逻辑
      • 3.配置文件+测试
    • 升级的方法@Around可以实现@Before, @After, @AfterReturning, @AfterThrowing
  • 总结

引出


spring可以new对象,给成员变量赋值,增强方法;

在这里插入图片描述在这里插入图片描述

Spring入门案例

初识Spring

image-20221104142926403

spring能干啥:
(1)new对象,放到spring容器中;
(2)给成员变量注入,依赖注入,控制反转;
(3)增强方法

在这里插入图片描述

在这里插入图片描述

入门案例1----用配置文件实现 Druid + JDBCTemplate + dao

1.之前的方式:new对象

package com.tianju;

import com.alibaba.druid.pool.DruidDataSource;
import com.tianju.dao.UserDaoImpl;
import com.tianju.entity.User;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

/**
 * 之前的方式,new对象,建立连接,拿到JDBCTemplate,然后dao层使用,到service,到servlet
 */
public class DemoDaoImpl {
    public static void main(String[] args) {
        // Druid
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/javaweb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("123");
        druidDataSource.setMaxActive(10);
        
        // JDBCTemplate
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(druidDataSource);

        // dao
        UserDaoImpl userDao = new UserDaoImpl();
        userDao.setJdbcTemplate(jdbcTemplate);
        List<User> list = userDao.queryAll();
        System.out.println(list);

    }
}

2.用配置文件的方法把new对象交给Spring

(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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

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
        http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    首先配置druid-->
<!--    id: ac.getBean("jdbcTemplate");用来从spring的容器中获取对象;
        class:交给spring来new的对象,两种情况:
                (1)自己写的类;
                (2)其他人写的类:
                <bean id="xxx" class="com.alibaba.druid.pool.DruidDataSource">
-->
<!--    TODO:替换:DruidDataSource druidDataSource = new DruidDataSource();-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--        spring给成员变量赋值-->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<!--        这里的url 需要在 & 符号后面加 amp; -->
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/javaweb?useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123"></property>
    </bean>

<!--    TODO:把JDBC也交给spring:JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(druidDataSource);-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--       给成员变量赋值,即jdbcTemplate.setDataSource(druidDataSource)-->
<!--       给成员变量赋值的两种方式:
            (1)直接设置value:<property name="password" value="123"></property>
            (2)通过id引用xml文件中的 ref:<property name="dataSource" ref="dataSource"></property>
            -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

<!--    TODO:把dao也交给spring:UserDaoImpl userDao = new UserDaoImpl();userDao.setJdbcTemplate(jdbcTemplate);-->
    <bean id="userDao" class="com.tianju.dao.impl.UserDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>
</beans>

3.如果要用对象,从spring的容器中获取ac.getBean(“userDao”);

package com.tianju.test;

import com.tianju.dao.IUserDao;
import com.tianju.entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

/**
 * 用户测试spring配置的是否好用
 */
public class JDBCTestDemo {
    public static void main(String[] args) {
        // TODO:直接从spring容器中获取dao
//        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        IUserDao userDaoImpl = (IUserDao) ac.getBean("userDao");
        List<User> userList = userDaoImpl.queryAll();
        userList.forEach(System.out::println);

    }
}

在这里插入图片描述

4.实体类和dao层的代码–问题:如果接口有两个实现类?

User.java文件

package com.tianju.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
 * 用户登陆的实体类
 */
@Data //包括get,set,toString
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    private String nickname;
    private Date createTime;
    private Date updateTime;
    private String imgUrl;
}

IUserDao.java接口文件

package com.tianju.dao;

import com.tianju.entity.User;

import java.util.List;

public interface IUserDao {
    List<User> queryAll();
}

UserDaoImpl.java实现类文件

package com.tianju.dao.impl;

import com.tianju.dao.IUserDao;
import com.tianju.entity.User;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.util.List;

/**
 * UserDao的实现类
 */
public class UserDaoImpl implements IUserDao {
    private JdbcTemplate jdbcTemplate;

    /**
     * set方法,用于给这个jdbcTemplate设置druidDataSource,
     * 从而可以使用这个jdbcTemplate
     * @param jdbcTemplate
     */
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public List<User> queryAll() {
        RowMapper<User> rowMapper = new BeanPropertyRowMapper<>(User.class);
        return jdbcTemplate.query("SELECT * FROM user_tab", rowMapper );
    }
}

【补充】获取spring容器中对象的两种方式:id 或 对象类型

(1)通过id获取,id是在xml配置文件中是唯一的:不会出现问题;

如果id重复,会报错:

Exception in thread “main” org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem:

Bean name ‘userDao’ is already used in this beans> element
Offending resource: class path resource [beans.xml]

IUserDao userDaoImpl = (IUserDao) ac.getBean("userDao");

(2)通过类的类型获取:

IUserDao userDaoImpl = ac.getBean(IUserDao.class);

此时如果接口有两个实现类,则会出现异常,Spring不知道应该取容器中两个对象中的哪一个,就会报错:

No qualifying bean of type ‘com.tianju.dao.IUserDao’ available: expected single matching bean but found 2: userDao,userDao1

入门案例2----person实体类对配置文件理解

在这里插入图片描述

person.java实体类文件

package com.tianju.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private Integer id;
    private String name;
    private Date birthday;

    public void init(){
        // 每次new出来都执行该方法
        System.out.println("每次new person对象时都执行的方法");
    }

    public void destroy(){
        // 在spring容器销毁时执行该方法
        System.out.println("spring容器销毁时执行的方法");
    }
}

(1)初始情况:当spring程序读到这一行时,就创建了一个person类,放到spring的容器中,其id为person;

<bean id="person" class="com.tianju.entity.Person" scope="singleton">

(2)参数scope="singleton"单例、scope="prototype"非单例:

无论是否为单例,都会执行init-method 方法;

如果是单例"singleton",关闭容器时会执行destroy方法;

如果不是单例"prototype",关闭容器时不会执行destroy方法;

<bean id="person" class="com.tianju.entity.Person" scope="singleton" init-method="init" destroy-method="destroy">

单例模式下,从容器中获取的都是同一个对象;==为true;

非单例模式下,从容器中获取的不是同一个对象;==为false;

(3)给成员变量赋值的方式 + 依赖注入

给成员变量赋值:(1)通过构造函数constructor-arg;(2)通过属性赋值property;

赋值有两种方式:(1)直接赋值value;(2)依赖注入ref;

在这里插入图片描述

通过构造函数赋值:

<!--    TODO:当spring程序读到这一行时,就创建了一个person类,id赋值为person,放到spring的容器中
        scope="singleton" 默认是单例:scope="prototype"
-->
    <bean id="person" class="com.tianju.entity.Person" scope="prototype" init-method="init" destroy-method="destroy">
<!--        有两种给成员变量赋值的方式,(1)构造函数;(2)通过属性赋值-->
        <constructor-arg name="id" value="100"></constructor-arg>
        <constructor-arg name="name" value="peter"></constructor-arg>
<!--        -->
        <constructor-arg name="birthday" ref="date"></constructor-arg>
    </bean>

<!--    依赖注入-->
    <bean id="date" class="java.util.Date"></bean>

通过属性赋值property:

    <bean id="person" class="com.tianju.entity.Person" scope="prototype" init-method="init" destroy-method="destroy">
<!--        有两种给成员变量赋值的方式,(1)构造函数;(2)通过属性赋值-->
        <property name="id" value="1"></property>
        <property name="name" value="peter"></property>
        <property name="birthday" ref="date"></property>

    </bean>

<!--    依赖注入-->
    <bean id="date" class="java.util.Date"></bean>

(4)测试文件执行顺序,new spring容器–读取bean.xml文件…

package com.tianju.test;

import com.tianju.entity.Person;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PersonTestDemo {
    public static void main(String[] args) {
        // 1.new ClassPathXmlApplicationContext spring创建了一个容器,用来放对象;
        // 2.读取bean.xml文件,如果配置了bean标签,就生成配置的对象,Person对象;
        // 3.把对象放到容器中,给成员变量赋值;
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        // 4.从容器中通过id获取对象;
        Person person = (Person)ac.getBean("person");
        // 5.从容器中通过类名获取对象;
        Person person1 = ac.getBean(Person.class);
        System.out.println("是否是同一个对象:"+(person1==person));

        // 关闭容器
        ac.close();
    }
}

Spring新建对象+给成员变量赋值—从配置文件到注解开发

在这里插入图片描述
在这里插入图片描述

用配置文件实现controller≈servlet

1.导包–用spring.verson实现版本控制

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tianju</groupId>
    <artifactId>spring0615</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--        进行spring的版本控制-->
        <spring.version>5.2.22.RELEASE</spring.version>
    </properties>

    <dependencies>
<!--        spring 的包,spring的容器,上下文,代表这个spring项目-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.16</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>
</project>

2.配置文件编写applicationContext.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
        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://127.0.0.1:3306/javaweb?useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123"></property>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <bean id="userDao" class="com.tianju.dao.impl.UserDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <bean id="userService" class="com.tianju.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>

    <bean id="userController" class="com.tianju.controller.UserController">
        <property name="userService" ref="userService"></property>
    </bean>
</beans>

3.进行测试ClassPathXmlApplicationContext

package com.tianju.test;

import com.tianju.controller.UserController;
import com.tianju.entity.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class TestXMLDemo {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserController userController = (UserController) ac.getBean("userController");
        List<User> userList = userController.queryAll();
        userList.forEach(System.out::println);
    }
}

用注解的方式实现controller

在这里插入图片描述

1.配置文件xml的更新context:component-scan

如果类上面标注了@Component(@Repository @Service @Controller) Spring就会new类,放容器中,@Autowired 自动注入值

<?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 https://www.springframework.org/schema/context/spring-context.xsd">

<!--    从com.tianju包下,扫描所有的类,
    如果类上面标注了@Component(@Repository @Service @Controller) Spring就会new类,放容器中,
    @Autowired 自动注入值-->
    <context:component-scan base-package="com.tianju"></context:component-scan>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/javaweb?useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123"></property>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

</beans>

2.在dao,service,controller上标注注解@Component(@Repository @Service @Controller) + @Autowired

在这里插入图片描述

比如Controller.java文件

package com.tianju.controller;

import com.tianju.entity.User;
import com.tianju.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;

/**
 * 现阶段就当是servlet
 */
@Controller
public class UserController {
    @Autowired
    IUserService userService;

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    public List<User> queryAll(){
        return userService.queryAll();
    }
}

3.进行测试ClassPathXmlApplicationContext

package com.tianju.test;

import com.tianju.controller.UserController;
import com.tianju.entity.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class TestControllerDemo {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserController userController = (UserController) ac.getBean("userController");
        List<User> userList = userController.queryAll();
        userList.forEach(System.out::println);
    }
}

用SpringConfig.java文件代替resource下的xml配置文件

在这里插入图片描述

3.用SpringConfig.java文件代替resource下的xml配置文件 @Configuration @ComponentScan @Bean

要点:

  • 1.如何告诉spring,这个文件是代替配置xml文件;@Configuration
  • 2.如何代替xml文件中context:component-scan,知道扫描哪些包;@ComponentScan(“com.tianju”)

要想实现代替xml配置文件,则还需要

  • 1.dataSource放到容器中;
  • 2.jdbcTemplate放到容器中;
  • 如果一个方法上加了@Bean,这个方法的返回值就在容器中了;方法名 就是id;

如果一个方法依赖其他方法,则

  • 如果一个方法依赖了容器中的对象,在该方法的参数中写这个对象名,
  • spring会把容器中的dataSource注入到方法中
package com.tianju.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

/**
 * 用来代替resources中的配置xml文件:
 * 1.如何告诉spring,这个文件是代替配置xml文件;@Configuration
 * 2.如何代替xml文件中context:component-scan,知道扫描哪些包;@ComponentScan("com.tianju")
 */
@Configuration
@ComponentScan("com.tianju")
public class SpringConfig {
    /**
     * 要想实现代替xml配置文件,则还需要
     * 1.dataSource放到容器中;
     * 2.jdbcTemplate放到容器中;
     * 如果一个方法上加了@Bean,这个方法的返回值就在容器中了;方法名 就是id;
     */
    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/javaweb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true");
        dataSource.setUsername("root");
        dataSource.setPassword("123");
        return dataSource;
    }

    /**
     * 如果一个方法依赖了容器中的对象,在该方法的参数中写这个对象名,
     * spring会把容器中的dataSource注入到方法中
     * @param dataSource 从容器中根据id获取 DataSource
     * @return
     */
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

}

4.进行测试AnnotationConfigApplicationContext

package com.tianju.test;

import com.tianju.config.SpringConfig;
import com.tianju.controller.UserController;
import com.tianju.entity.User;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;
import java.util.List;

/**
 * 测试配置文件SpringConfig.java
 */
public class TestConfigDemo1 {
    public static void main(String[] args) {
        // 用java的config文件,代替配置文件xml
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 获取所有bean的名字
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        System.out.println(Arrays.toString(beanDefinitionNames));
        UserController userController = ac.getBean(UserController.class);
        List<User> list = userController.queryAll();
        list.forEach(System.out::println);
    }
}

SpringCofig.java文件引入properties文件—解耦druid + 引入其他config.java

在这里插入图片描述

在这里插入图片描述

1.引入jdbc.properties配置文件@PropertySource(“classpath:jdbc.properties”)+@Value(“${jdbc.url}”)

在上面的方式中,又把jdbc耦合到了java代码中,如果在resources下有一个jdbc相关配置的jdbc.properties文件,如何在springConfig.java文件中读取配置文件?

jdbc.properties文件

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/javaweb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
jdbc.username=root
jdbc.password=123

更新后的SpringConfig.java文件

package com.tianju.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
/**
 * 用来代替resources中的配置xml文件
 * 注解 @Configuration表示是spring的配置类,用来代替 applicationContext.xml文件的;
 * 注解 @ComponentScan("com.tianju") 用来代替 <context:component-scan base-package="com.tianju"></context:component-scan>;
 */

@Configuration
@ComponentScan("com.tianju")
// TODO:如果想把jsbc用配置文件弄出来
// 引入其他的配置文件
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {

    @Value("${jdbc.driverClassName}")
    private String diverClassName;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    /**
     * 要想实现代替xml配置文件,则还需要
     * 1.dataSource放到容器中;
     * 2.jdbcTemplate放到容器中;
     * 如果一个方法上加了@Bean,这个方法的返回值就在容器中了;方法名 就是id;
     */
    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(diverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    /**
     * 如果一个方法依赖了容器中的对象,在该方法的参数中写这个对象名,
     * spring会把容器中的dataSource注入到方法中
     * @param dataSource 从容器中根据id获取 DataSource
     * @return
     */
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
}

进行测试AnnotationConfigApplicationContext

package com.tianju.test;

import com.tianju.config.SpringConfig;
import com.tianju.controller.UserController;
import com.tianju.entity.User;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.List;

public class TestPropertiesDemo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserController userController = ac.getBean(UserController.class);
        List<User> userList = userController.queryAll();
        userList.forEach(System.out::println);
    }
}

2.引入其他的config.java文件@Import(SpringConfig.class)

package com.tianju.config;

import org.springframework.context.annotation.Import;

/**
 * 引入其他配置文件 @Import(SpringConfig.class)
 */
@Import(SpringConfig.class)
public class SConfig {
}

配置单例/多例,初始化化方法,销毁方法

在这里插入图片描述

  • 注解 :@Controller 扫描时,发现了有这句话就会new对象出来;

代替 bean id=“userController” class=“com.tianju.controller.UserController”>

  • id:默认不写小字母小写,如果自己指定,则用 @Controller(“userController”)

  • 单例:默认是单例;如果想设置不是单例,则 @Scope(value = “PROTOTYPE”)

  • 初始化方法:@PostConstruct:在构造函数之后运行

  • 销毁方法:@PreDestroy;在容器销毁之前执行;单例ac.close()执行;

  • 注解:@Autowired,用来代替property name=“userService” ref=“userService”>/property>

1.@Scope(value = “singleton”) prototype + @PostConstruct + @PreDestroy

实体类Person.java代码

package com.tianju.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor

@Component
@Scope(value = "singleton") // singleton prototype
public class Person {
    private Integer id;
    private String name;
    private Date birthday;

    @PostConstruct
    public void init(){
        // 每次new出来都执行该方法
        System.out.println("每次new person对象时都执行的方法");
    }

    @PreDestroy
    public void destroy(){
        // 在spring容器销毁时执行该方法
        System.out.println("spring容器销毁时执行的方法");
    }
}

2.配置文件@Configuration @ComponentScan(“com.tianju”) + 测试AnnotationConfigApplicationContext

配置文件SpringConfig.java文件

package com.tianju.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.tianju")
public class SpringConfig {
}

测试文件

package com.tianju.test;

import com.tianju.config.SpringConfig;
import com.tianju.entity.Person;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringConfigTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        Person person = ac.getBean(Person.class);
        System.out.println(person);
        ac.close();
    }
}

如果一个接口有两个实现类—入门案例的问题

在这里插入图片描述

注入的时候:1.按照类型注入,寻找IUserService的实现类注入进来;

  • 2.方案1:如果有多个实现类,则按照变量名字的id在容器中找对应的实现类;或者按照3解决
  • 3.方案2:意外情况:如果变量名不想改,怎么搞? 可以配合 @Qualifier(“userServiceImp1”) 进行指定;
  • 4.方案3:用一个注解@Resource(name = “userServiceImpl1”),既可以注入,也可以指定,代替@Autowired 和 @Qualifier(“userServiceImpl1”);
  • 补充:@Autowired 是spring开发的; @Resource是java自身的;

1.方案一:指定名字—指定其中的一个实现类userServiceImpl

package com.tianju.controller;

import com.tianju.entity.User;
import com.tianju.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;

/**
 * 现阶段就当是servlet
 */
@Controller
public class UserController {
    @Autowired
    IUserService userServiceImpl;

    // 如果上面标注了 @Autowired, 下面就不用写了
    public void setUserService(IUserService userService) {
        this.userServiceImpl = userService;
    }

    public List<User> queryAll(){
        return userServiceImpl.queryAll();
    }
}

2.方案二:用注解 @Qualifier(“userServiceImp2”) 进行指定 + @Autowired

package com.tianju.controller;

import com.tianju.entity.User;
import com.tianju.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import java.util.List;

/**
 * 现阶段就当是servlet
 */
@Controller

public class UserController {
    
    @Autowired
    @Qualifier("userServiceImpl2")
    IUserService userService;

    public List<User> queryAll(){
        return userService.queryAll();
    }
}

3.方案三:用一个注解@Resource(name = “userServiceImpl”)替换上面的两个

package com.tianju.controller;

import com.tianju.entity.User;
import com.tianju.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;
import java.util.List;

/**
 * 现阶段就当是servlet
 */
@Controller

public class UserController {
    
    @Resource(name = "userServiceImpl")
    IUserService userService;

    public List<User> queryAll(){
        return userService.queryAll();
    }
}

补充代码:

package com.tianju.controller;

import com.tianju.entity.User;
import com.tianju.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.List;


/**
 * 现阶段它就是servlet
 * 注解 :@Controller 扫描时,发现了有这句话就会new对象出来;
 * 代替<bean id="userController" class="com.tianju.controller.UserController">
 *   id:默认不写小字母小写,如果自己指定,则用 @Controller("userController")
 *   单例:默认是单例;如果想设置不是单例,则 @Scope(value = "PROTOTYPE")
 *   初始化方法:@PostConstruct:在构造函数之后运行
 *   销毁方法:@PreDestroy;在容器销毁之前执行
 *     注解:@Autowired,用来代替<property name="userService" ref="userService"></property>
 */
@Controller("userController")
//@Scope(value = "prototype") // 指定不是单例
public class UserController {
    // 自己new的对象,不在容器中,只有spring管理的才会在容器中;
    // 因此这里不能自己new,要交给spring
//    @Autowired // TODO:方案3,用一个注解@Resource(name = "userServiceImpl1") 代替 @Autowired 和 @Qualifier("userServiceImpl1")
    // TODO:如果有两个实现类,怎么解决:方案一:指定一下名字
    /**
     * 注入的时候:1.按照类型注入,寻找IUserService的实现类注入进来;
     *          2.方案1:如果有多个实现类,则按照变量名字的id在容器中找对应的实现类;或者按照3解决
     *          3.方案2:意外情况:如果变量名不想改,怎么搞? 可以配合  @Qualifier("userServiceImp1") 进行指定;
     *          4.方案3:用一个注解@Resource(name = "userServiceImpl1"),既可以注入,也可以指定
     *            代替@Autowired 和 @Qualifier("userServiceImpl1");
     *         补充:@Autowired 是spring开发的; @Resource是java的
     */
//    @Qualifier("userServiceImpl1") // TODO:方案2,用注解 @Qualifier("userServiceImp1") 进行指定
    @Resource(name = "userServiceImpl1") // TODO:方案3,用一个注解@Resource(name = "userServiceImpl1") 代替 @Autowired 和 @Qualifier("userServiceImpl1")

    private IUserService userService;
//    private IUserService userServiceImpl; // TODO:方案1.指定名字

//    public void setUserService(IUserService userService) {
//        this.userService = userService;
//    }

    @PostConstruct // 在构造函数之后运行
    public void init(){
        System.out.println("控制器 Controller init");
    }
    @PreDestroy // 在容器销毁之前执行
    public void destroy(){
        System.out.println("Controller destroy");
    }

    public List<User> queryAll(){
        return userService.queryAll();
//        return userServiceImpl.queryAll(); // TODO:方案1.指定名字
    }

}

Spring增强方法——给一批类全部做增强

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

用配置文件做增强

在这里插入图片描述

1.增强类LogActiveDemo.java文件

package com.tianju.aop;

import org.springframework.stereotype.Component;

/**
 * 增强类---用来给别的类做增强
 * 1.需要在容器中
 */
@Component
public class LogActiveDemo {
    public void before(){
        System.out.println("增强类的before==========");
    }
    public void after(){
        System.out.println("增强类的 after==========");
    }
    public void afterReturning(){
        System.out.println("增强类的 beforeReturning==========");
    }
    public void afterThrowing(){
        System.out.println("增强类的 beforeThrowing==========");
    }
}

2.被增强的类UserController.java文件

package com.tianju.controller;

import org.springframework.stereotype.Controller;

/**
 * 被增强的类---被增强类增强
 * 1.需要在容器中;
 */
@Controller
public class UserController {
    public void add(){
        System.out.println("add a new user");
    }
}

3.进行增强与被增强的配置

aop:config+
aop:aspect+
pointcut=“execution(* com.tianju.controller.UserController.*(…))”

在这里插入图片描述如果是所有类的所有方法做增强:

pointcut=“execution( * com.tianju.controller. * .*(…))”

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"
       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.tianju"></context:component-scan>

<!--    进行增强方法的配置-->
    <aop:config>
<!--        增强类是容器中的 logActiveDemo -->
        <aop:aspect id="logActiveDemo" ref="logActiveDemo">
<!--           pointcut="execution(* com.tianju.controller.UserController.*(..))" 作用在所有方法上-->
            <aop:before method="before" pointcut="execution(* com.tianju.controller.UserController.*(..))"></aop:before>
            <aop:after method="after" pointcut="execution(* com.tianju.controller.UserController.*(..))"></aop:after>
            <aop:after-returning method="afterReturning" pointcut="execution(* com.tianju.controller.UserController.*(..))"></aop:after-returning>
            <aop:after-throwing method="afterThrowing" pointcut="execution(* com.tianju.controller.UserController.*(..))"></aop:after-throwing>
        </aop:aspect>

    </aop:config>

</beans>

4.测试用例及其结果ClassPathXmlApplicationContext(“beans.xml”);

package com.tianju.test;

import com.tianju.controller.UserController;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LogDemoTest1 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        UserController userController = ac.getBean(UserController.class);
        userController.add();
    }
}

在这里插入图片描述

用注解做增强

在这里插入图片描述

1.增强类LogActiveDemo.java文件 @Aspect,(@Before(“execution(* com.tianju.controller.UserController.*(…))”), @After, @AfterReturning, @AfterThrowing)

增强类—用来给别的类做增强

  • 1.需要在容器中 @Component;
  • 2.标识自己是增强类 @Aspect;
  • 3.自己的方法作用于什么时候@Before, @After, @AfterReturning, @AfterThrowing;
  • 4.标识自己要给哪些方法做增强,用自定义注解
package com.tianju.aop;

import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 增强类---用来给别的类做增强
 * 1.需要在容器中 @Component;
 * 2.标识自己是增强类 @Aspect;
 * 3.要给哪些类做增强 用自定义注解实现
 */
@Component
@Aspect
public class LogActiveDemo {
    @Before("execution(* com.tianju.controller.UserController.*(..))")
    public void before(){
        System.out.println("增强类的before==========");
    }
    @After("execution(* com.tianju.controller.UserController.*(..))")
    public void after(){
        System.out.println("增强类的 after==========");
    }
    @AfterReturning("execution(* com.tianju.controller.UserController.*(..))")
    public void afterReturning(){
        System.out.println("增强类的 beforeReturning==========");
    }
    @AfterThrowing("execution(* com.tianju.controller.UserController.*(..))")
    public void afterThrowing(){
        System.out.println("增强类的 beforeThrowing==========");
    }
}

2.自定义注解MyAnnoClass.java文件@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME)

package com.tianju.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解,进行是否增强类的选择
 */
@Target({ElementType.TYPE}) // 这个注解作用在类上
@Retention(RetentionPolicy.RUNTIME) // 在运行时阶段增强
public @interface MyAnnoClass {
}

3.被增强的类UserController.java文件@MyAnnoClass

被增强的类—被增强类增强

  • 1.需要在容器中 @Controller;
  • 2.标识自己这个类被增强,用自定义注解 @MyAnnoClass
package com.tianju.controller;

import com.tianju.anno.MyAnnoClass;
import org.springframework.stereotype.Controller;

/**
 * 被增强的类---被增强类增强
 * 1.需要在容器中 @Controller;
 * 2.标识自己这个类被增强,用自定义注解 @MyAnnoClass
 */
@Controller
@MyAnnoClass
public class UserController {
    public void add(){
        System.out.println("add a new user");
    }
}

4.配置文件SpringConfig.java文件开启动态代理 @EnableAspectJAutoProxy

package com.tianju.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.tianju")
@EnableAspectJAutoProxy // 让动态代理生效
public class SpringConfig {
}

5.测试用例AnnotationConfigApplicationContext(SpringConfig.class);

package com.tianju.test;

import com.tianju.config.SpringConfig;
import com.tianju.controller.UserController;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LogConfigDemoTest1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserController userController = ac.getBean(UserController.class);
        userController.add();
    }
}

简化:从 @Before(“execution(* com.tianju.controller.UserController.*(…))”) 到@After(“@annotation(com.tianju.anno.MyAnnoMethod)”)

在这里插入图片描述

1.自定义注解MyAnnoMethod.java文件@Target({ElementType.METHOD})

package com.tianju.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 标识哪些方法要做加强,替换
 * @Before("execution(* com.tianju.controller.UserController.*(..))")
 */

@Target({ElementType.METHOD}) // 这个注释作用在方法上
@Retention(RetentionPolicy.RUNTIME) // 以后全部用这个,运行时阶段
public @interface MyAnnoMethod {
}

2.增强类LoginActiveAnnoMethod.java文件@Before(“@annotation(com.tianju.anno.MyAnnoMethod)”)

增强类—给别的类的方法做增强

  • 1.在容器中;
  • 2.是增强类;
  • 3.标注可以给哪些方法做增强
package com.tianju.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;


/**
 * 增强类---给别的类的方法做增强
 * 1.在容器中;
 * 2.是增强类;
 * 3.标注可以给哪些方法做增强
 */
@Component
@Aspect
public class LoginActiveAnnoMethod {
    @Before("@annotation(com.tianju.anno.MyAnnoMethod)")
    public void before(){
        System.out.println("~~~~~~~~~~~~~~~利用标注了某个注解的 方法 进行增强~ 增强方法的 before 方法~~~~~~~~~~");
    }
}

3.被增强类OpusController.java文件@MyAnnoMethod

package com.tianju.controller;

import com.tianju.anno.MyAnnoMethod;
import org.springframework.stereotype.Controller;

@Controller
public class OpusController {
    @MyAnnoMethod // 会被增强
    public void add(){
        System.out.println("标注 @MyAnnoMethod 注解 被增强类的某个方法增强");
    }

    // 没有标注@MyAnnoMethod,不会被增强
    public void insert(){
        System.out.println("没有标注 @MyAnnoMethod 注解");
    }
}

4.配置文件SpringConfig.java文件开启动态代理 @EnableAspectJAutoProxy

package com.tianju.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.tianju")
@EnableAspectJAutoProxy // 让动态代理生效
public class SpringConfig {
}

5.测试AnnotationConfigApplicationContext(SpringConfig.class)

package com.tianju.test;

import com.tianju.config.SpringConfig;
import com.tianju.controller.OpusController;
import com.tianju.controller.UserController;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class LogMyAnnoMethodTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        OpusController opusController = ac.getBean(OpusController.class);
        opusController.add();
        System.out.println("________________________");
        opusController.insert();
    }
}

在这里插入图片描述

另一种方式:@Before(“@within(org.springframework.stereotype.Controller)”) + 日志的案例

1.定义一个增强方法,标注@within

LogActiveWith.java文件;@Before(“@within(org.springframework.stereotype.Controller)”)

增强别的类时,通过JoinPoint能够

  • 1.能知道访问的类是啥;
  • 2.能知道访问的目标方法是啥;
  • 3.能知道访问传的参数是啥;
package com.tianju.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Date;

/**
 * 增强类--给别的方法做增强
 * 1.在容器中;
 * 2.是增强类;
 * 3.给哪些方法做增强;
 */

@Component // 在容器中
@Aspect // 是增强类
public class LogActiveWith {
    /**
     * 增强别的类时,通过JoinPoint能够
     * 1.能知道访问的类是啥;
     * 2.能知道访问的目标方法是啥;
     * 3.能知道访问传的参数是啥;
     * @param joinPoint
     */
    @Before("@within(org.springframework.stereotype.Controller)")
    public void before(JoinPoint joinPoint){
        // 1.获取被增强的方法名
        String className = joinPoint.getTarget().getClass().getName();
        // 2.获取访问的目标方法是啥
        String methodName = joinPoint.getSignature().getName();
        // 3.能知道访问时传的参数是啥
        Object[] args = joinPoint.getArgs();
        System.out.println(
                "在"+new Date()
                + "时,访问了" + className
                + "类的," + methodName
                + "方法,传的参数为 "+ Arrays.toString(args));
    }
}

2.正常写controller的逻辑

MoneyController.java文件

package com.tianju.controller;

import org.springframework.stereotype.Controller;

/**
 * 被增强的类,
 * 1.在容器中;2.被增强;
 * 记录交易的日志数据
 */
@Controller
public class MoneyController {
    public void pay(Double money){
        System.out.println("~~~~~~~进行支付~~~~~~");
    }

    public void income(Double income){
        System.out.println("~~~~~~~~~~收入~~~~~~~~~");
    }
}

3.配置文件+测试

配置文件SpringConfig.java文件,@EnableAspectJAutoProxy

package com.tianju.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.tianju")
@EnableAspectJAutoProxy // 让动态代理生效
public class SpringConfig {
}

测试用例

package com.tianju.test;

import com.tianju.config.SpringConfig;
import com.tianju.controller.MoneyController;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MoneyDemoTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        MoneyController moneyController = ac.getBean(MoneyController.class);
        moneyController.pay(500.58);
        moneyController.income(458.69);
    }
}

打印出的日志信息

在这里插入图片描述

升级的方法@Around可以实现@Before, @After, @AfterReturning, @AfterThrowing

around方法,环绕方法

  • 可以替代之前的before,after,afterReturning,afterThrowing
  • 1.在容器中;2.是增强方法;3.给谁做增强
package com.tianju.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 * around方法,环绕方法
 * 可以替代之前的before,after,afterReturning,afterThrowing
 * 1.在容器中;2.是增强方法;3.给谁做增强
 */
@Component
@Aspect
public class LogActiveAround {

    @Around("@within(org.springframework.stereotype.Controller)")
    public void around(ProceedingJoinPoint joinPoint){
        String className = joinPoint.getTarget().getClass().getName();// 获取被增强的类名
        String methodName = joinPoint.getSignature().getName();// 获取被增强类的方法名
        Object[] args = joinPoint.getArgs();//获取增强方法的参数
        // 1.@before 在方法执行前做一些事情;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String beforeAspectLog = "【执行前】在" + sdf.format(new Date())+"时,开始执行"+className+"类的"+methodName+"方法,传的参数是"+ Arrays.toString(args);
        System.out.println(beforeAspectLog);
        try {
            // 此时方法执行也由joinPoint控制
            joinPoint.proceed(args); // 执行目标方法
            // 2.在方法正常执行完成后做一些事情;
            System.out.println("正常执行完成");
        } catch (Throwable e) {
            // 3.@AfterThrowing 在抛出异常后执行代码
            String afterThrowingLog = "【异常】在" + sdf.format(new Date())+"时,执行"+className+"类的"+methodName+"方法,传的参数是"+ Arrays.toString(args) +"出现异常";
            System.out.println(afterThrowingLog);
        } finally {
            // 4.@AfterReturning 在返回后执行代码
            String afterReturningLog = "【完成】在" + sdf.format(new Date())+"时,完成了"+className+"类的"+methodName+"方法,传的参数是"+ Arrays.toString(args);
            System.out.println(afterReturningLog);
        }
    }
}

总结

spring可以new 对象,给对象属性赋值,增强方法;
要记住spring的常用注解;

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/673674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NodeFormer:一种用于节点分类的可扩展图结构学习Transformer

文章目录 NodeFormer: A Scalable Graph Structure Learning Transformer for Node ClassificationAbstract方法General Model and Key ChallengesEfficient Learning Discrete Structures可微随机结构学习Input Structures as Relational BiasLearning Objective NodeFormer: …

网络的基础介绍

文章目录 1. 网络发展2. 认识 "协议"3. 网络协议初识3.1 协议分层 4. OSI七层模型4.1 TCP/IP五层(或四层)模型 5. 网络传输基本流程5.1 同一个网段内的主机文件传输5.2 认识MAC地址5.3 跨网段的主机文件传输 6. 数据包封装和分用 1. 网络发展 很早之前&#xff0c;计…

基于强化学习(Reinforcement learning,RL)的机器人路径规划MATLAB

一、Q-learning算法 Q-learning算法是强化学习算法中的一种&#xff0c;该算法主要包含&#xff1a;Agent、状态、动作、环境、回报和惩罚。Q-learning算法通过机器人与环境不断地交换信息&#xff0c;来实现自我学习。Q-learning算法中的Q表是机器人与环境交互后的结果&#…

[unity]Pico VR unity开发笔记(一)

Pico VR 开发笔记&#xff08;一&#xff09; XR Interaction Tooikit 版本 2.3.2 一、环境搭建 其实官方文档已经写的很详细了&#xff0c;这里只是不废话快速搭建&#xff0c;另外有一项官方说明有误的&#xff0c;补充说明一下&#xff0c;在开发工具部分说明 插件安装——…

深度学习基础——通过PyTorch构建神经网络实现1维/2维序列分类

文章目录 使用3层前馈神经网络使用循环神经网络生成pickle数据集构建RNN进行1维序列的训练、推理 使用3层前馈神经网络 通过PyTorch构建前馈神经网络&#xff0c;并对二维数据点进行分类。在该例子当中&#xff0c;所有的训练数据和测试数据都是通过高斯混合模型GMM生成的&…

网络 - 你可知 Telnet 能通但是 Ping 不通百思不得其解

问题描述 以前本人以为 telnet 通 ping 一定也是通的&#xff0c;telnet 能通&#xff0c;表示两台计算机之间建立了连接通道。理论上是能 ping 通的。 但是今天万万没想到&#xff0c;并不是这样... 原因分析 如果不能 ping 通&#xff0c;可能的原因是对方主机关闭了 ping…

MYSQL阶段_DAY01~DAY11(附笔记)

注意&#xff1a;&#xff08;数据表如下&#xff09; sort表&#xff1a; user表&#xff1a; zhangwu表&#xff1a; 1.Part1 JDBC操作数据库的步骤 1.注册驱动 告知JVM使用的是哪一个数据库的驱动, 把驱动类的对象交给DriverManager管理&#xff0c;用于…

一文理解MySQL的For Update行级锁

一文理解MySQL的For Update行级锁 引言一、MySQL的For Update简介1.1、For Update的作用1.2、For Update与其他锁定方式的区别 二、For Update的语法2.1、SELECT语句的基本语法2.2、mysql如何开启事务和提交事务&#xff1f;2.3、使用For Update进行数据锁定 三、如何使用For U…

王道计算机网络学习笔记(2)——物理层

前言 文章中的内容来自B站王道考研计算机网络课程&#xff0c;想要完整学习的可以到B站官方看完整版。 二&#xff1a;物理层 2.1.1&#xff1a;物理层基本概念 2.1.2&#xff1a;数据通信基本知识 1、数据通信模型和基本概念 通信目的是为了传递消息&#xff08;消息&…

2022 年第十二届 MathorCup 高校数学建模挑战赛D题思路(移动通信网络站址规划和区域聚类问题)

目录 一、前言 二、问题背景 三、问题 四、解题思路 &#xff08;1&#xff09;针对问题1&#xff1a; &#xff08;2&#xff09;针对问题2&#xff1a; &#xff08;3&#xff09;针对问题3&#xff1a; 五、附上几个典型代码 &#xff08;1&#xff09;K-means算法…

6月16日,企业快成长技术创新论坛厦门站大数据专场开启!

全球大数据规模增长快速&#xff0c;2020年全球新增数据规模为64ZB&#xff0c;是2016年的400%&#xff0c;2035年新增数据将高达2140ZB1&#xff0c;大数据呈现指数级增长。随着数字经济的发展和数字化转型的深入&#xff0c;愈来愈多的数据资源正以数据要素的形态独立存在并参…

STM32F4_DS18B20红外温度传感器

目录 前言 1. 单总线时序结构 2. DS18B20结构 2.1 DS18B20操作流程 2.2 DS18B20数据帧 3. 温度存储格式 4. 硬件分析 5. 实验程序详解 5.1 main.c 5.2 DS18B20.c 5.3 DS18B20.h 前言 STM32F4内部集成了温度传感器。在之前的学习中&#xff0c;我们已经学习了使用AD进…

宁波天一永安杯初赛 wp-AGCTS战队

文章目录 MISCZipSimpleDocumentBeautifulImage WebDeserializationCodeCheck CryptoSecretRsa MobilePeacock pwnwingtip REPolenta MISC Zip ARCHPR 直接数字爆破&#xff0c;得到二进制密码&#xff0c;得 flag SimpleDocument Kali binwalk 发现里面有一 pdf 文件&#…

DRIFTINGBLUES: 3实战演练

文章目录 DRIFTINGBLUES: 3实战演练一、前期准备1、相关信息 二、信息收集1、端口扫描2、访问网站3、访问网页4、翻译内容5、访问网页6、翻译内容8、查看源码9、解密10、访问网页11、写入shell并登录12、连接shell13、查找nc14、反弹shell 三、后渗透1、进入家目录查找文件2、写…

分布式应用 ----- 点对点(p2p)网络

目录 1. 概述 1.1. P2P的概念 1.2. P2P产生的背景 1.3. P2P的优劣势 2. P2P分类 2.1. 根据中央化程度 2.2. 根据网络拓扑结构 3. NAT技术详解 3.1. 概述 3.2. NAT的优劣势 3.3. NAT穿透常见解决方案 3.4. 探针打洞基本原理 3.4.1. 基本原理 3.4.2. 同一个NAT网关内…

2023年企业云盘排行榜,这些产品值得尝试!

在当今信息技术高度发达的时代&#xff0c;企业对于信息的存储和管理需求越来越高。因此&#xff0c;企业云盘逐渐成为了企业存储与管理的重要组成部分。企业云盘能够实现多设备共享、远程控制、安全备份、合作办公等多种功能&#xff0c;方便高效地解决企业内部信息管理问题。…

【AIGC】17、MM-OVOD | 同时使用文本示例和图像示例来指导分类

文章目录 一、背景二、方法2.1 框架总览2.1.1 Text-based classifiers from language descriptions2.1.2 Vision-based Classifiers from Image Exemplars2.1.3 Constructing Classifiers via Multi-Modal Fusion 三、效果3.1 数据集3.2 实现细节3.3 开集目标检测结果 论文&…

双向交错CCM图腾柱无桥单相PFC学习仿真与实现(2)SOGI_PLL学习仿真总结

目录 前言 SOGI基本原理 锁相环基本原理 仿真实现及说明 总结 前言 前面总结了双向交错CCM图腾柱无桥单相PFC系统实现&#xff0c;后面把问题细分&#xff0c;关于SOGI锁相环的应用和学习在这里总结下。 双向交错CCM图腾柱无桥单相PFC学习仿真与实现&#xff08;1&#x…

Collection接口详细介绍(下)

前言&#xff1a; 本篇文章主要讲解Java中的Collection接口以及相关实现类的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出&#xff0c;对大佬有帮助希望可以支持下哦~ 小威在此先感谢各位小伙伴儿了&#x1f601…

CSDN 周赛 59 期

CSDN 周赛 59 期 前言判断题单选题题目1题目2填空题编程题1、题目名称:坏掉的打字机2、题目名称:布尔零点计数小结前言 由于最近,csdn 每日一练新增了两个题目,按照惯例,那么新增的题目,会就近出现在最近的 CSDN 周赛中,嗯,经常参加周赛,并关注每日一练社区的小伙伴应…