spring ico容器 spring注入方式 spring与tomcat整合

这篇具有很好参考价值的文章主要介绍了spring ico容器 spring注入方式 spring与tomcat整合。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、简介

1、什么是spring?

2、目的

3、功能及使用范围

二、spring IOC

1、ioc的理解

2、开发人员可达到的目的

3、分析实现

4、bean配置

三、spring IOC的注入方式

1、set方法属性注入

2、构造注入

3、自动装配

四、spring与tomcat的整合/spring与web容器的整合

五、spring AOP

1、aop的特点

2、AOP中关键性概念  

3、前置通知

1.1、准备工作

 1.2、前置通知

4、后置通知

5、环绕通知

6、异常通知

7、过滤通知

8、AOP的总结

8.1、概念

8.2、应用

六、spring中bean的生命周期

1、spring管理JavaBean初始化过程

1.1、思维导图

1.2、spring容器管理JavaBean的初始化过程(spring中bean的生命周期)。

2、spring的JavaBean管理中单例模式及原型模式

2.1、spring中JavaBean是单例还是多例。


一、简介

1、什么是spring?

Spring是一个开源的轻量级Java应用开发框架,它提供了一种简单、高效、灵活的方式来构建企业级应用程序。Spring框架的核心特点是依赖注入Dependency Injection)和面向切面编程Aspect-Oriented Programming),它通过一组模块化的组件提供全面的支持,使开发人员能够快速搭建可扩展、可维护的应用。

2、目的

学习Spring的目的可以总结为以下几点:

  1. 简化开发:Spring提供了一系列的工具和抽象,简化了企业级应用开发过程。它通过依赖注入来解决对象间的依赖关系,使得代码更加灵活、可测试和可维护。
  2. 高效开发:Spring框架提供了诸多模块,如Spring MVC、Spring Boot等,可以快速构建Web应用和微服务。它提供了一种约定优于配置的开发方式,提高了开发效率。
  3. 提高可扩展性:Spring框架基于接口和模块化设计,能够方便地集成其他开源框架和库。它的松耦合特性使得应用程序更易于扩展和维护。
  4. 丰富的功能:Spring拥有丰富的功能和特性,包括事务管理、安全性、缓存、消息队列、调度等。它为开发人员提供了一系列解决方案,使得应用程序开发更加便捷。

3、功能及使用范围

Spring的功能范围非常广泛,包括但不限于以下方面:

  1. 依赖注入和控制反转:通过依赖注入,Spring容器能够将对象之间的依赖关系管理起来,使得对象的创建和使用解耦,提高代码的灵活性和可测试性。
  2. 面向切面编程:Spring提供了面向切面编程(AOP)的支持,可以将与核心业务逻辑无关的功能(如事务管理、日志记录等)进行横切,提高了代码的重用性和可维护性。
  3. Web开发支持:Spring提供了Spring MVC模块,用于开发Web应用程序。它能够处理HTTP请求和响应,进行URL路由、数据绑定、表单验证、视图解析等操作,简化了Web开发过程。
  4. 数据访问支持:Spring框架提供了对各种数据访问技术的支持,包括JDBC、ORM(如Hibernate、MyBatis)、JPA等。它通过抽象出一套统一的数据访问接口,使得数据库访问更加方便和可替换。
  5. 安全性支持:Spring提供了一套强大的安全性框架,可以进行认证和授权管理。它支持各种身份验证方式,如基于表单的认证、基于角色的访问控制等,保护应用程序的安全性。

总之,Spring框架是Java开发领域最流行的框架之一,它提供了丰富的功能和特性,帮助开发人员构建可靠、高效的企业级应用程序。

一句话概括,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

二、spring IOC

1、ioc的理解

IoC(Inversion of Control,控制反转是Spring框架的核心概念之一,也是实现依赖注入的基础。它通过解耦对象之间的依赖关系,使得对象的创建和管理由框架来负责,而不是由开发人员手动管理。

在传统的程序设计中,对象之间的依赖关系通常由开发人员在代码中进行硬编码,对象直接通过关键字(如new)来创建和管理。这种方式存在一些问题,如对象之间的耦合度高、可测试性差、扩展性差等。

而IoC则是一种思想上的转变,它将对象的创建和管理权利交给了框架。具体来说,IoC的核心思想是:通过配置或注解,告诉框架需要创建哪些对象,以及对象之间的依赖关系。然后,框架在应用程序运行时根据配置信息动态地创建和组装对象。

Spring通过IoC容器来实现控制反转。IoC容器是一个用于管理对象的容器,它负责创建、组装、初始化和销毁对象。开发人员只需要配置对象的创建和依赖关系,然后通过容器来获取需要的对象即可。

2、开发人员可达到的目的

  1. 解耦对象之间的依赖关系:通过IoC容器,开发人员只需要关注对象的功能实现,而不需要关心对象是如何创建和组装的。对象之间的依赖关系由容器负责管理,降低了对象之间的耦合度。
  2. 提高代码的可测试性:由于对象的创建和组装由容器来完成,开发人员可以很容易地对对象进行替换或模拟,从而实现单元测试和集成测试。
  3. 增强代码的可扩展性:当需要添加新的功能或模块时,只需要配置新的对象和依赖关系,而不需要修改现有的代码。通过配置方式,可以方便地在不影响现有代码的情况下进行扩展。
  4. 提高代码的灵活性:IoC容器使得对象的创建完全可配置化,可以在运行时根据需要创建不同的实例。同时,框架提供了生命周期管理和依赖解析等功能,使得对象的管理更加便捷。

总而言之,IoC是Spring框架的核心特性之一,它通过控制反转的思想,将对象的创建和依赖关系的管理交给了框架,减少了对象之间的耦合度,提高了代码的可测试性和可扩展性。

3、分析实现

首先创建好我们的maven项目

spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

 设置我们的pom.xml

    <dependency>
    		<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<!-- 2、导入spring依赖 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- 5.1、junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- 5.2、servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>${javax.servlet.version}</version>
			<scope>provided</scope>
		</dependency>

新建spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

我们用原来的方式写一下

  1. 编写一个接口
    public interface UserService {
        public void updUser();
    }
  2. 再编写一个实现类
    public class UserServiceImpl1 implements UserService {
        public void updUser() {
            System.out.println("修改SQL用户数据");
    }

    我们原来的方式是这样写的

  3. 现在我们添加一个实现类

    public class UserServiceImpl2 implements UserService {
        public void updUser() {
            System.out.println("修改SQL用户数据");
            //修改用户姓名
            System.out.println("修改用户姓名");
        }
    }
  4. 当我们测试调方法的时候只需要改动后面的实现类spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

  5. 手动实例化的弊端:
    1、一旦依赖的接口实现需要大批量改动,迭代,维护成本高
     2、当接口的实现类不统一,维护成本更高

我们怎么解决这个问题呢?

4、bean配置

首先我们要在maven项目里面的resources文件里面建立一个基于spring的xml文件spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

<?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>

 我们在web文件里面建立两个Class类

public class UserAction {
    private UserService us;

    public UserService getUs() {
        return us;
    }

    public void setUs(UserService us) {
        this.us = us;
    }

    public String updUser() {
        us.updUser();
        return "list";
    }

}
public class GoodsAction {
    private UserService us;

    public UserService getUs() {
        return us;
    }

    public void setUs(UserService us) {
        this.us = us;
    }

    public String updUser() {
        us.updUser();
        return "list";
    }

}

编写一个测试类

public class demo1 {
    public static void main(String[] args) {
//        加载spring核心配置文件(建模),获取spring的上下文对象,上下文对象中可以获取任何JavaBean对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
        UserAction userAction = (UserAction) context.getBean("userAction");
        userAction.updUser();
        GoodsAction goodsAction = (GoodsAction) context.getBean("goodsAction");
        goodsAction.updUser();
    }
}

在我们的新建的这个spring-context.xml文件里面添加<bean>

<?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">

    <!--凡是在spring核心配置文件spring-context.xml中配置,那么该类JavaBean就交给了spring容器管理-->
    <bean class="com.tgq.ioc.web.UserAction" id="userAction">
        <property name="us" ref="userService1"/>
    </bean>

    <bean class="com.tgq.ioc.web.GoodsAction" id="goodsAction">
        <property name="us" ref="userService2"/>
    </bean>
    <bean class="com.tgq.ioc.service.impl.UserServiceImpl1" id="userService1"/>
    <bean class="com.tgq.ioc.service.impl.UserServiceImpl2" id="userService2"/>
</beans>


 

三、spring IOC的注入方式

spring的ioc有哪些注入方式呢?

  1. set方法属性注入
  2. 构造注入
  3. 接口注入/自动装配

1、set方法属性注入

在我们前面的GoodsAction新添几个属性和get、set方法,一个输出打印的方法toPrint()

public class GoodsAction {
    private UserService us;
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<String> getPeoples() {
        return peoples;
    }

    public void setPeoples(List<String> peoples) {
        this.peoples = peoples;
    }

    private List<String> peoples;

    public UserService getUs() {
        return us;
    }

    public void setUs(UserService us) {
        this.us = us;
    }

    public String updUser() {
        us.updUser();
        return "list";
    }
    public void toPrint() {
        System.out.println(this.name);
        System.out.println(this.age);
        System.out.println(this.peoples);
    }

}

在print-context.xml里面设置值,使用set方法属性注入用property

    <bean class="com.tgq.ioc.web.GoodsAction" id="goodsAction">
        <property name="us" ref="userService2">
        </property>
        <property name="name" value="旺财"/>
        <property name="age" value="20"/>
        <property name="peoples">
            <list>
                <value>留守儿童</value>
                <value>情侣</value>
                <value>留守老人</value>
            </list>
        </property>
    </bean>

在测试类里面调用

goodsAction.toPrint();

spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

2、构造注入

在我们的User Action里面添加属性及有参无参的构造方法,一个输出打印的方法toPrint()

public class UserAction {
    private UserService us;
    private String name;
    private int age;
    private List<String> hobby;

    public UserAction() {
    }

    public UserAction(String name, int age, List<String> hobby) {
        this.name = name;
        this.age = age;
        this.hobby = hobby;
    }

    public UserService getUs() {
        return us;
    }

    public void setUs(UserService us) {
        this.us = us;
    }

    public String updUser() {
        us.updUser();
        return "list";
    }
    public void toPrint() {
        System.out.println(this.name);
        System.out.println(this.age);
        System.out.println(this.hobby);
    }
}

在print-context.xml里面设置值,使用构造输入需要用constructor-arg标签

    <bean class="com.tgq.ioc.web.UserAction" id="userAction">
        <property name="us" ref="userService1"/>
        <constructor-arg name="name" value="l"/>
        <constructor-arg name="age" value="18"/>
        <constructor-arg name="hobby">
            <list>
                <value>唱</value>
                <value>跳</value>
                <value>rap</value>
            </list>
        </constructor-arg>
    </bean>

继续在测试类里面调用toPrint方法

spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

3、自动装配

自动装配中byName和byType的区别:

byName:在配置好的文件中变量名不更改就不会报错。按照属性的名称进行自动装配。

  1. 当一个bean的属性名称与其他bean的id匹配时,Spring容器会自动将该bean注入到对应的属性中。
  2. 如果找不到匹配的bean,则会抛出异常。
  3. 在XML配置中,可以使用autowire="byName"@Autowired注解实现byName自动装配。

byType:会在整个spring中寻找JavaBean,按照属性的类型进行自动装配。

  1. 当一个bean的属性的类型与其他bean的class匹配时,Spring容器会自动将该bean注入到对应的属性中。
  2. 如果有多个匹配的bean,则会抛出异常,需要进行更具体的限定或使用@Qualifier注解来解决。
  3. 在XML配置中,可以使用autowire="byType"@Autowired注解实现byType自动装配。

四、spring与tomcat的整合/spring与web容器的整合

我们的xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byName"
       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">

    <!--凡是在spring核心配置文件spring-context.xml中配置,那么该类JavaBean就交给了spring容器管理-->
    <bean class="com.tgq.ioc.web.UserAction" id="userAction">
        <property name="us" ref="userService1"/>
    </bean>

    <bean class="com.tgq.ioc.web.GoodsAction" id="goodsAction">
        <property name="us" ref="userService2"/>
    </bean>
    <bean class="com.tgq.ioc.service.impl.UserServiceImpl1" id="userService1"/>
    <bean class="com.tgq.ioc.service.impl.UserServiceImpl2" id="userService2"/>
</beans>

spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

编写一个过滤器

@WebListener
public class sprintListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("初始化");
        //spring的上下文
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
//tomcat上下文
        ServletContext servletContext = sce.getServletContext();

        servletContext.setAttribute("sprintContext", context);

    }
}

编写servlet类调用它

@WebServlet("userlist")
public class Userservlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到sprint的上下文对象
        ClassPathXmlApplicationContext Context = (ClassPathXmlApplicationContext) req.getServletContext().getAttribute("sprintContext");
        UserService bean = (UserService) Context.getBean("userService1");
        System.out.println(bean);
        bean.updUser();

    }
}

启动服务器就完成了整合

spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

五、spring AOP

Spring AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架的一个重要模块,提供了在应用程序中进行横切关注点的模块化支持。

1、aop的特点

  1. 非侵入性:Spring AOP采用编译期间的代理方式实现切面功能,不需要修改原始类的代码。使用者可以在不侵入原有代码的情况下,将切面逻辑插入到目标对象的方法中,实现对横切关注点的处理。
  2. 松耦合:Spring AOP通过使用切面来处理横切关注点,将关注点的实现与主要业务逻辑进行分离。切面可以独立于应用程序进行开发和测试,并且可以通过配置和织入的方式来将切面应用到不同的目标对象上,实现代码的松耦合性。
  3. 横切关注点的集中化管理:Spring AOP支持将相同的横切关注点集中定义在一个切面中,并在需要的地方进行切入。这使得横切关注点的管理更加方便,可以避免代码的重复。
  4. 与IoC容器的集成:Spring AOP与Spring IoC容器无缝集成,可以借助IoC容器来管理切面和目标对象,实现AOP配置的灵活性和可扩展性。通过注解或XML配置,可以方便地将切面和目标对象注入到容器中并进行织入操作。
  5. 支持丰富的切点表达式:Spring AOP支持使用切点表达式对目标对象的方法进行精确选择。切点表达式可以根据方法名称、参数、返回类型等条件来定义切点,灵活地进行切面织入。
  6. 支持不同类型的通知:Spring AOP提供了多种类型的通知,如前置通知、后置通知、环绕通知、异常通知和最终通知。用户可以选择合适的通知类型,并定义切面的处理逻辑。
  7. 可扩展性:Spring AOP对切面的实现支持继承和组合的机制,可以通过实现Advice接口或继承现有的Advice类来进行切面的定制和扩展。这样使得开发者能够根据具体需求来实现自定义的切面逻辑。

Spring AOP提供了一种灵活、非侵入性的横切关注点处理机制,通过将关注点的实现与主要业务逻辑分离,实现代码的解耦和管理的集中化。同时,与Spring IoC容器的集成以及丰富的切点表达式和通知类型,使得Spring AOP具有很高的扩展性和灵活性。

我们一般会用到系统的日志功能

2、AOP中关键性概念  

AOP中专业术语
名称 描述 注释
连接点(Joinpoint) 程序执行过程中明确的点,如方法的调用,或者异常的抛出.
目标对象(Target) 被通知(被代理)的对象 完成具体的业务逻辑
通知(Advice) 在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理) 完成切面编程
代理(Proxy) 将通知应用到目标对象后创建的对象(代理=目标+通知),例子:外科医生+护士 只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的
切入点(Pointcut) 多个连接点的集合,定义了通知应该应用到那些连接点。 也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序
适配器(Advisor) 适配器=通知(Advice)+切入点(Pointcut)

3、前置通知

1.1、准备工作

如果需要可以创建如图一样的项目结构

spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

  1. 编写接口
    public interface IBookBiz {
        // 购物
        public boolean buy(String userName, String bookName, Double price);
    
        // 发表评论
        public void comment(String userName, String comments);
    }
     
  2. 实现上面的接口
    
    public class BookBizImpl implements IBookBiz {
    
    	public BookBizImpl() {
    		super();
    	}
    
    	public boolean buy(String userName, String bookName, Double price) {
    		// 通过控制台的输出方式模拟购书
    		if (null == price || price <= 0) {
    			throw new PriceException("book price exception");
    		}
    		System.out.println(userName + " buy " + bookName + ", spend " + price);
    		return true;
    	}
    
    	public void comment(String userName, String comments) {
    		// 通过控制台的输出方式模拟发表书评
    		System.out.println(userName + " say:" + comments);
    	}
    
    }
  3. 编写一个异常类

    public class PriceException extends RuntimeException {
    
    	public PriceException() {
    		super();
    	}
    
    	public PriceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    		super(message, cause, enableSuppression, writableStackTrace);
    	}
    
    	public PriceException(String message, Throwable cause) {
    		super(message, cause);
    	}
    
    	public PriceException(String message) {
    		super(message);
    	}
    
    	public PriceException(Throwable cause) {
    		super(cause);
    	}
    	
    }
  4. 配置spring-context.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           default-autowire="byType"
           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">
        <!--aop的javabean-->
        <!--对象-->
        <bean class="com.tgq.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
    
    </beans>
  5. 编写一个测试类

    public class demo {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
    
            IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");
    
            bookBiz.buy("小牛子", "钢铁是怎样炼成的", 99.9d);
    
            bookBiz.comment("小牛子", "睡不着,来劲了");
    
        }
    }
  6. 测试结果spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

 1.2、前置通知

添加一个通知类,需要继承MethodBeforeAdvice 重写方法

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
//		在这里,可以获取到目标类的全路径及方法及方法参数,然后就可以将他们写到日志表里去
		String target = arg2.getClass().getName();
		String methodName = arg0.getName();
		String args = Arrays.toString(arg1);
		System.out.println("【前置通知:系统日志】:"+target+"."+methodName+"("+args+")被调用了");
	}

}

配置通知类,代理,在代理里面配置目标对象和通知

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byType"
       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">

    <!--aop的javabean-->
    <!--对象-->
    <bean class="com.tgq.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
    <!--通知-->
    <bean class="com.tgq.aop.advice.MyMethodBeforeAdvice" id="beforeAdvice"></bean>
    <!--    代理        -->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="factoryBean">
        <!--        配置目标对象        -->
        <property name="target" ref="bookBiz"></property>
        <!--        配置代理接口,目标对象接口        -->
        <property name="proxyInterfaces">
            <list>
                <value>com.tgq.aop.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知        -->
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
            </list>
        </property>
    </bean>
</beans>

编写测试类

public class demo {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");

        IBookBiz bookBiz = (IBookBiz) context.getBean("factoryBean");

        bookBiz.buy("小牛子", "钢铁是怎样炼成的", 99.9d);

        bookBiz.comment("小牛子", "睡不着,来劲了");

    }
}

结果spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

4、后置通知

 在前面的基础上再写一个后置通知的类,需要实现AfterReturningAdvice ,重写afterReturning方法

public class MyAfterReturningAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		String target = arg3.getClass().getName();
		String methodName = arg1.getName();
		String args = Arrays.toString(arg2);
		System.out.println("【后置通知:买书返利】:"+target+"."+methodName+"("+args+")被调用了,"+"该方法被调用后的返回值为:"+arg0);

	}

}

配置xml

    <!--aop的javabean-->
    <!--对象-->
    <bean class="com.tgq.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
    <!--    前置通知-->
    <bean class="com.tgq.aop.advice.MyMethodBeforeAdvice" id="beforeAdvice"></bean>
    <!-- 后置通知 -->
    <bean class="com.tgq.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
    <!--    代理        -->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="factoryBean">
        <!--        配置目标对象        -->
        <property name="target" ref="bookBiz"></property>
        <!--        配置代理接口,目标对象接口        -->
        <property name="proxyInterfaces">
            <list>
                <value>com.tgq.aop.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知        -->
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
                <value>myAfterReturningAdvice</value>
            </list>
        </property>
    </bean>

测试结果spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

5、环绕通知

编写一个环绕通知类,实现MethodInterceptor接口,重写方法

public class MyMethodInterceptor implements MethodInterceptor {//Interceptor拦截器的意思

    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable {
        String target = arg0.getThis().getClass().getName();
        String methodName = arg0.getMethod().getName();
        String args = Arrays.toString(arg0.getArguments());
        System.out.println("【环绕通知调用前:】:" + target + "." + methodName + "(" + args + ")被调用了");
//		arg0.proceed()就是目标对象的方法
        Object proceed = arg0.proceed();
        System.out.println("【环绕通知调用后:】:该方法被调用后的返回值为:" + proceed);
        return proceed;
    }

}

配置xml

    <!--aop的javabean-->
    <!--对象-->
    <bean class="com.tgq.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
    <!--    前置通知-->
    <bean class="com.tgq.aop.advice.MyMethodBeforeAdvice" id="beforeAdvice"></bean>
    <!-- 后置通知 -->
    <bean class="com.tgq.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
    <!--    环绕通知-->
    <bean class="com.tgq.aop.advice.MyMethodInterceptor" id="myMethodInterceptor"/>
    <!--    代理        -->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="factoryBean">
        <!--        配置目标对象        -->
        <property name="target" ref="bookBiz"></property>
        <!--        配置代理接口,目标对象接口        -->
        <property name="proxyInterfaces">
            <list>
                <value>com.tgq.aop.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知        -->
        <property name="interceptorNames">
            <list>
<!--                <value>beforeAdvice</value>-->
<!--                <value>myAfterReturningAdvice</value>-->
                <value>myMethodInterceptor</value>
            </list>
        </property>
    </bean>

测试结果spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

6、异常通知

编写一个异常通知类,实现ThrowsAdvice 接口,编写方法,方法名必须是afterThrowing

public class MyThrowsAdvice implements ThrowsAdvice {
    public void afterThrowing(PriceException ex) {
        System.out.println("【异常通知】:当价格发生异常,那么执行此处代码块!!!");
    }
}

配置xml文件

<!--aop的javabean-->
    <!--对象-->
    <bean class="com.tgq.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
    <!--    前置通知-->
    <bean class="com.tgq.aop.advice.MyMethodBeforeAdvice" id="beforeAdvice"></bean>
    <!-- 后置通知 -->
    <bean class="com.tgq.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
    <!--    环绕通知-->
    <bean class="com.tgq.aop.advice.MyMethodInterceptor" id="myMethodInterceptor"/>
    <!--异常通知-->
    <bean class="com.tgq.aop.advice.MyThrowsAdvice" id="myThrowsAdvice"/>
    <!--    代理        -->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="factoryBean">
        <!--        配置目标对象        -->
        <property name="target" ref="bookBiz"></property>
        <!--        配置代理接口,目标对象接口        -->
        <property name="proxyInterfaces">
            <list>
                <value>com.tgq.aop.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知        -->
        <property name="interceptorNames">
            <list>
                <!--                <value>beforeAdvice</value>-->
                <!--                <value>myAfterReturningAdvice</value>-->
                <value>myMethodInterceptor</value>
                <value>myThrowsAdvice</value>
            </list>
        </property>
    </bean>

测试,如果我们的价格有问题会出现异常通知

public class demo {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");

//        IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");

        IBookBiz bookBiz = (IBookBiz) context.getBean("factoryBean");

        bookBiz.buy("小牛子", "钢铁是怎样炼成的", -99.9d);

        bookBiz.comment("小牛子", "睡不着,来劲了");

    }
}

测试结果spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

7、过滤通知

我们配置我们的过滤通知,需要在xml里面进行配置

 <!--aop的javabean-->
    <!--对象-->
    <bean class="com.tgq.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
    <!--    前置通知-->
    <bean class="com.tgq.aop.advice.MyMethodBeforeAdvice" id="beforeAdvice"></bean>
    <!-- 后置通知 -->
    <bean class="com.tgq.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
    <!--    环绕通知-->
    <bean class="com.tgq.aop.advice.MyMethodInterceptor" id="myMethodInterceptor"/>
    <!--异常通知-->
    <bean class="com.tgq.aop.advice.MyThrowsAdvice" id="myThrowsAdvice"/>
    <!--    过滤通知-->
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="regexpMethodPointcutAdvisor">
        <!--        给我们的后置通知做过滤-->
        <property name="advice" ref="myAfterReturningAdvice"/>
        <!--        给我们的购物做过滤-->
        <property name="pattern" value=".*buy"/>
    </bean><!--正则匹配我们的切入点-->
    <!--    代理        -->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="factoryBean">
        <!--        配置目标对象        -->
        <property name="target" ref="bookBiz"></property>
        <!--        配置代理接口,目标对象接口        -->
        <property name="proxyInterfaces">
            <list>
                <value>com.tgq.aop.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知        -->
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
                <!--                <value>myAfterReturningAdvice</value>-->
                <!--                使用过滤通知需要把原有的配置注释或者删除-->
                <value>regexpMethodPointcutAdvisor</value>
                <value>myMethodInterceptor</value>
                <value>myThrowsAdvice</value>
            </list>
        </property>
    </bean>

</beans>

 测试结果,我们的评论后就没有返利了,我们只有购物后评论前才有返利spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

8、AOP的总结

8.1、概念


aop是面向切面编程,程序是由上至下执行,但是aop面向切面编程不是,aop的程序执行,首先当程序执行到目标对象的目标方法时,如果连接点上由前置通知,则先执行前置通知,再执行目标方法,如果没有前置通知,则先执行前置通知,再执行目标方法,如果没有前置通知,则继续执行目标方法;再查看目标方法上是否有后置通知,如果有,则再执行后置通知代码。

8.2、应用

不管是前置通知、后置通知、环绕通知、异常通知还是过滤通知,代码都是非业务核心代码,比如日志和事务的管理。


我们还可以去学习一下:jdk代理与cglib代理,aop数据字典等其他

六、spring中bean的生命周期

  1. 初始化 init
  2. 使用 service
  3. 销毁 destroy

1、spring管理JavaBean初始化过程

1.1、思维导图

spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java

BeanDefinition:包含了很多属性和方法。例如:id、class(类名)、

scope、ref(依赖的bean)等等。其实就是将bean(例如<bean>)的定义信息

存储到这个对应BeanDefinition相应的属性中


例如:

<bean id="" class="" scope=""> -----> BeanDefinition(id/class/scope)

Aware感知接口:在实际开发中,经常需要用到Spring容器本身的功能资源。

例如:BeanNameAware、ApplicationContextAware等等

BeanDefinition 实现了 BeanNameAware、ApplicationContextAware


 

BeanPostProcessor:后置处理器。在Bean对象实例化和引入注入完毕后,

在显示调用初始化方法的前后添加自定义的逻辑。(类似于AOP的绕环通知)

前提条件:如果检测到Bean对象实现了BeanPostProcessor后置处理器才会执行

Before和After方法

BeanPostProcessor


 

BeanDefinitionReader:解析Bean的定义。在Spring容器启动过程中,会将Bean解析成Spring内部的BeanDefinition结构;

理解为:将spring.xml中的<bean>标签转换成BeanDefinition结构

有点类似于XML解析


 

BeanPostProcessor:后置处理器。在Bean对象实例化和引入注入完毕后,

在显示调用初始化方法的前后添加自定义的逻辑。(类似于AOP的绕环通知)

前提条件:如果检测到Bean对象实现了BeanPostProcessor后置处理器才会执行

Before和After方法

BeanPostProcessor

1.2、spring容器管理JavaBean的初始化过程(spring中bean的生命周期)。

  1. xml/annotation/configuation配置JavaBean
  2. BeanDefinitionReader解析配置的JavaBean得到BeanDefinition,最终得到List<BeanDefinition>集合。
  3. 触发BeanFactoryPoatProcessor,JavaBean初始化之前执行自己的业务。
  4. spring中beanFactory,会通过List<BeanDefinition>集合遍历初始化所有的JavaBean对象。
  5. 如果自己的JavaBean需要调动spring上下文中的资源,那么需要实现*Aware感知接口
  6. 如果自己的JavaBean已经初始化好了,还需要扩展功能,那么需要借助BeanPostProcessor来实现。

2、spring的JavaBean管理中单例模式及原型模式

2.1、spring中JavaBean是单例还是多例。

  1. 默认是单例的,但是可以配置多例的。
  2. 单例的优点:节约内存;弊端:有变量污染;
    多例的优点:无变量污染;弊端:消耗内存;
    public class ParamAction {
        private int age;
        private String name;
        private List<String> hobby;
        private int num = 1;//初始值
        // private UserBiz userBiz = new UserBizImpl1();
    
        public ParamAction() {
            super();
        }
    
        public ParamAction(int age, String name, List<String> hobby) {
            super();
            this.age = age;
            this.name = name;
            this.hobby = hobby;
        }
    
        public void execute() {
            // userBiz.upload();
            // userBiz = new UserBizImpl2();
            System.out.println("this.num=" + this.num++);
            System.out.println(this.name);
            System.out.println(this.age);
            System.out.println(this.hobby);
        }
    }
     
     
     @org.junit.Test
        public void test1() {
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
    //        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-context.xml");
    
            ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");
            ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
            System.out.println("p1 == p2:" + (p1 == p2));
            if (p1 != null && p2 != null) {
                p1.execute();
                p2.execute();
            }
    
            applicationContext.close();
            //		单例时,容器销毁instanceFactory对象也销毁;多例时,容器销毁对象不一定销毁;
        }
    xml配置
        <!--    spring的生命周期-->
        <!--  默认单例模式  -->
        <!--多例模式:prototype--><!--单例模式:singleton-->
        <bean id="paramAction" class="com.tgq.beanLife.ParamAction" scope="singleton">
            <constructor-arg name="name" value="三丰"></constructor-arg>
            <constructor-arg name="age" value="21"></constructor-arg>
            <constructor-arg name="hobby">
                <list>
                    <value>抽烟</value>
                    <value>烫头</value>
                    <value>大保健</value>
                </list>
            </constructor-arg>
        </bean>
    spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java
  3. 单例:JavaBean是跟着spring上下文初始化的;(容器生对象生,容器死对象死)
    多例:JavaBean是使用的时候才会创建,销毁跟着jvm走。
     
    public class InstanceFactory {
    	public void init() {
    		System.out.println("初始化方法");
    	}
    
    	public void destroy() {
    		System.out.println("销毁方法");
    	}
    
    	public void service() {
    		System.out.println("业务方法");
    	}
    }
    xml配置
        <bean id="instanceFactory" class="com.tgq.beanLife.InstanceFactory"
              scope="singleton" init-method="init" destroy-method="destroy"></bean>
     
        @org.junit.Test
        public void test2() {//
    //        多例不会调用我们的初始化方法
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
    //多例模式的时候,只要调用就会初始化
            InstanceFactory instanceFactory = (InstanceFactory) applicationContext.getBean("instanceFactory");
        }
    spring ico容器 spring注入方式 spring与tomcat整合,spring,tomcat,java
    // BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式
    // 默认情况下bean的初始化,单例模式立马会执行,但是此时XmlBeanFactory作为子类,单例模式下容器创建,bean依赖没有初始化,只有要获取使用bean对象才进行初始化
    @org.junit.Test
    public void test3() {
        // ClassPathXmlApplicationContext applicationContext = new
        // ClassPathXmlApplicationContext("/spring-context.xml");

        Resource resource = new ClassPathResource("/spring-context.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
//        调用会初始化
//		InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");

    }

什么情况下会使用多例:一个类里面的属性值有变化,会使用多例文章来源地址https://www.toymoban.com/news/detail-652635.html

到了这里,关于spring ico容器 spring注入方式 spring与tomcat整合的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring框架,以及和spring框架相关的Java面试题和spring ioc的注入方式

    目录 一.spring来源,以及介绍 1.spring诞生的背景 2.spring框架 介绍 3.spring框架在使用中的优点以及不足 3.1优点  3.2不足 3.3总结 4.为什么要使用spring  二.将spring框架部署在IDEA中  1.替换pom.xml  2.构建spring所需要的xml文件 三.spring的三种注入方式 0.定义需要的类,方法 1.方法注入

    2024年02月12日
    浏览(51)
  • .NET 6 整合 Autofac 依赖注入容器

    一行业务代码还没写,框架代码一大堆,不利于学习。 常看到java的学习资料或博客,标题一般为《SpringBoot 整合 XXX》,所以仿照着写了《.NET 6 整合 Autofac 依赖注入容器》这样一个标题。 以下是我自己的用法,可能不是最佳实践。 NuGet搜索并安装: Autofac Autofac.Extensions.Depe

    2023年04月26日
    浏览(47)
  • spring boot java项目整合Scala&Spark,接口api调用方式调用scala代码,配置分享

    版本说明: spring boot: 2.5.9 jdk:1.8 spark:2.4.5 sclala:2.11.12 首先你需要有一个完美的spring boot项目(java版本)能成功运行,这就不赘述了,按照网上的自己搭建吧,然后重要的来了,我捣鼓了两天时间,各样的报错见过了,网上的处理方法要嘛是不全,要嘛是没有用,各种办

    2024年02月10日
    浏览(52)
  • SpringBoot 底层机制分析【Tomcat 启动+Spring 容器初始化+Tomcat 如何关联Spring 容器】【下】

    😀前言 本篇博文是关于SpringBoot 底层机制分析实现,希望能够帮助你更好的了解SpringBoot 😊 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动力😉😉 💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客

    2024年02月13日
    浏览(45)
  • spring boot--自动化注入组件原理、内嵌tomcat-1

    前言 我们知道开发spring boot项目,在启动类上添加注解@SpringBootApplication ,然后引入要自动注入的组件依赖,然后现application.properties中加上相应配置就可以自动注入这个组件,那么下面看看自动注入组件是如何实现的 一、@SpringBootApplication 注解 1、查看SpringBootApplication 类如下

    2024年02月15日
    浏览(40)
  • Spring整合tomcat的WebSocket详细逻辑(图解)

    主要解决存在的疑问 为什么存在2种spring整合websocket的方式,一种是使用@ServerEndpoint注解的方式,一种是使用@EnableWebSocket注解的方式,这2种有什么区别和联系?可以共存吗?它们实现的原理是什么?它们的各种配置到底是什么意思?@EnableWebSocket是如何完成配置的? 在服务端

    2024年02月07日
    浏览(37)
  • spring——依赖注入原理及注入方式

    🟣1.依赖注入(Dependency Injection,DI) 是一种设计模式和编程技术,其原理是将对象的依赖关系由外部容器来管理和注入。它的目的是解耦组件之间的依赖关系,提高代码的灵活性、可维护性和可测试性。 🟣2.依赖注入的原理 是通过在对象的构造函数、属性或方法中注入所依

    2024年02月08日
    浏览(43)
  • Spring框架IOC容器和DI依赖注入

    IOC(Invertion Of Control):控制反转,使用对象时,由使用new创建对象转变为由外部提供对象,此过程中对象的创建控制权由程序转移到外部的思想称之为控制反转. DI(Dependency Injection):依赖注入,在容器中建立bean与bean之间的关系的过程,称之为依赖注入 pom.xml依赖引入 BookDao BookDaoImpl Book

    2023年04月09日
    浏览(89)
  • 使用@Configuration和@Bean给spring容器中注入组件

    以前我们是使用配置文件来注册bean的,现如今可以用@Configuration 来代替配置文件。

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包