Spring 概述
Spring是一个轻量级的Java 开发框架,框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。
Spring的核心是控制反转(IoC)和面向切面(AOP)
Spring意义
首先我们来看一段代码
dao接口:
dao接口:
package com.test.dao;
public interface userdao {
void select();
}
mysqldaoimpl:
package com.test.dao;
public class mysqldaoimpl implements userdao{
public void select() {
System.out.println("mysqldaoimpl");
}
}
mssqldaodimpl:
package com.test.dao;
public class mssqldaoimpl implements userdao {
public void select() {
System.out.println("mssqlselect ");
}
}
test类:
package com.test.domain;
import com.test.dao.mysqldaoimpl;
import com.test.dao.userdao;
public class test1 {
public static void main(String[] args) {
userdao mysqldaoimpl = new mysqldaoimpl();
mysqldaoimpl.select();
}
}
这里写了一个接口代表某一个查询方法,然后写了2个实现类,分别是mysql的连接和mssql的连接查询
我们可以注意到,我们在test类里面想要调用mysql的方法就直接new了一个实现类的对象,那么如果在后面想要mssql的查询的话,就需要修改代码,这样的代码效率不高,而且在后面代码如果多了也不好改了。而且这样写的话控制权全在开发者手里,而不是在用户的手里,要实现什么样的功能控制权应该是在用户手里,而不是开发者手里。
那么这里就可以用到 Spring框架
首先也还是配置一下spring的坐标。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
配置完成后,就来配置一下我们的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="mysqldaoimpl" class="com.test.dao.mysqldaoimpl"/>
<bean id="mssqldaoimpl" class="com.test.dao.mssqldaoimpl"/>
</beans>
test类:
package com.test.domain;
import com.test.dao.userdao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test1 {
public static void main(String[] args) {
ApplicationContext cl = new ClassPathXmlApplicationContext("bean.xml"); //传入xml文件
userdao mysqldaoimpl = (userdao)cl.getBean("mysqldaoimpl"); //获取mysqldaoimpl方法
mysqldaoimpl.select();//调用mysqldaoimpl方法
}
}
配置并直接传入xml文件,并获取一下方法,就可以直接来调用方法就可以使用了。无需在new实现类的实例化对象,
Spring使用
bean对象的创建来于容器,bean对象中的所有属性,都有容器来注入。下面来看看常用的几种注入方式
构造注入
使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置
的方式,让 spring 框架来为我们注入
首先定义一个实体类
package com.test.doamin;
import java.util.Date;
public class Perpon {
private String name;
private Integer age;
public Perpon() {
}
@Override
public String toString() {
return "Perpon{" +
"name='" + name + '\'' +
", age=" + age +
", date=" + date +
'}';
}
public Perpon(String name, Integer age, Date date) {
this.name = name;
this.age = age;
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
private Date date;
}
在平时我们都是直接在new的时候,或者是使用set方式对他进行赋值,那么在spring框架下,只需要配置一下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="person" class="com.test.doamin.Perpon">
<constructor-arg name="name" value="xiaoming"/>
<constructor-arg name="age" value="18"/>
<constructor-arg name="date" ref="now"/>
</bean>
<bean id = "now" class="java.util.Date"/>
</beans>
test类:
public static void main(String[] args) {
ApplicationContext cl = new ClassPathXmlApplicationContext("bean.xml"); //传入xml文件
Perpon person = (Perpon) cl.getBean("person");
System.out.println(person);
}
}
注意事项:类中需要提供一个对应参数列表的构造函数。
然后我们就可以看到执行结果了。
Perpon{name='xiaoming', age=18, date=Sun Aug 30 05:32:35 CST 2020}
把person打印出来,这里看到这些成员变量都被赋值了,是由我们框架去完成的。
constructor-arg标签属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
Set 注入
<bean id="person" class="com.test.doamin.Perpon">
<property name="name" value="xiaoming"/>
<property name="age" value="18"/>
<property name="date" ref="now"/>
</bean>
<bean id = "now" class="java.util.Date"/>
property标签属性:
name:找的是类中 set 方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的
实际开发中,此种方式用的较多。
Bean 自动装载
在spring框架里面可以自动装配Bean。我们只需要在bean标签里面加上 autowire就可以了。
autowire属性
person类:
person类:
package com.test.doamin;
public class Perpon {
private String name;
private Dong dog;
public Perpon() {
}
private Cat cat;
public Perpon(String name, Dong dog, Cat cat) {
this.name = name;
this.dog = dog;
this.cat = cat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dong getDog() {
return dog;
}
public void setDog(Dong dog) {
this.dog = dog;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
}
cat与dog类:
package com.test.doamin;
public class Cat {
public void method(){
System.out.println("cat");
}
}
这两个实体类代码基本一样,就不复制多份了。
这些基本写好后,就可以来配置一下beans.xml文件了
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">
<bean id="person" class="com.test.doamin.Perpon" autowire="byName">
<property name="name" value="xiaoming"/>
</bean>
<bean id="cat" class="com.test.doamin.Cat"/>
<bean id="dog" class="com.test.doamin.Dong"/>
</beans>
写好后,我们再来写test类
public static void main(String[] args) {
ApplicationContext cl = new ClassPathXmlApplicationContext("bean.xml"); //传入xml文件
Perpon person = (Perpon) cl.getBean("person");
System.out.println(person.getName());
person.getCat().method();
person.getDog().method();
}
这样的配置就更简单写了,在使用byName的时候会自动在容器上下文查找和自己对象set方法后面的值对应的bean id。
Spring Aop实现
Aop概念:
软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
Aop核心概念
1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)
对连接点进行拦截的定义
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
Aop 实现方式一
在使用前需要导入一个依赖包
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
<scope>runtime</scope>
</dependency>
定义一个serivce的接口:
package com.test.service;
public interface serivce {
void add();
void delete();
void update();
void qurey();
}
serivce实现类:
package com.test.service;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class serivceimpl implements serivce {
public void add() {
System.out.println("添加用户");
}
public void delete() {
System.out.println("删除用户");
}
public void update() {
System.out.println("修改用户");
}
public void qurey() {
System.out.println("查询用户");
}
}
定义完成后,我们需要在不修改代码的情况下,增强一下他的功能的话,以前会直接使用动态代理来实现。但是那也定义起来很麻烦。这里就可以使用到Aop
。
这里再来定义2个方法,分别是方法执行前执行的方法,和方法执行后执行的方法。也叫做前置增强和后置增强
package com.test.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class log implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName()+"De"+method.getName()+"方法执行了");
}
}
我们这直接让他继承了MethodBeforeAdvice接口,继承该接口后面配置完aop后会在方法执行前进行执行。
方法参数:
1.method 要被激发的方法
2.args 方法的参数
3.target 目标对象,可能为null
定义后置增强方法:
package com.test.log;
import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class Afterlog implements AfterReturningAdvice {
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("执行了"+method.getName()+"执行结果为"+o);
}
}
定义完这样后,我们就可以来配置beans.xml文件了。
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: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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="serivce" class="com.test.service.serivceimpl"/>
<bean id="log" class="com.test.log.log"/>
<bean id="afterlog" class="com.test.log.Afterlog"/>
<aop:config>
<!-- 声明切入点,并且使用expression表达式设置需要执行的位置-->
<aop:pointcut id="pointcut" expression="execution(* com.test.service.serivceimpl.*(..))"/>
<!-- advice-ref:设置需要切入的功能,pointcut-ref:设置需要切入的点 -->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
Aop 实现方式二
前面需要定义并且继承接口,现在可以用了另一种方式,直接定义为一个类,然后在bean.xml里面配置就可以了。
定义一个增强类,写上前置增强和后置增强的方法。
package com.test.log;
public class logp {
public void before(){
System.out.println("方法执行前执行");
}
public void after(){
System.out.println("方法执行后执行");
}
}
配置beans.xml文件
<bean id="serivce" class="com.test.service.serivceimpl"/>
<bean id="log" class="com.test.log.log"/>
<bean id="afterlog" class="com.test.log.Afterlog"/>
<bean id="logs" class="com.test.log.logp"/>
<aop:config>
<aop:aspect ref="logs">
<aop:pointcut id="point" expression="execution(* com.test.service.serivceimpl.*(..))"/>
<!-- 使用前置增强 引用point-->
<aop:before method="before" pointcut-ref="point"/>
<!-- 使用后置增强 引用point-->
<aop:after method="before" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
标签:xml,name,Spring,void,笔记,学习,test,com,public
From: https://www.cnblogs.com/gk0d/p/16866495.html