Введение в весну
Весна - это каркас с открытым исходным кодом, слоистые Javaee One-Stop Rapide.
Так называемая универсальная структура означает, что Spring имеет все уровни решений, разработанных JavaEE.
- ВЕБ-слой: SpringMVC
- Сервисный уровень: управление компонентами Spring, декларативные транзакции.
- Слой DAO: шаблон Spring JDBC, шаблон ORM
преимущество:
- IOC: удобная развязка
- АОП: расширение программы
- легкий каркас
- Простая интеграция с другими фреймворками
Весеннее использование
Введение в каталог после пакета воспроизведения пружины распакован:
- документы: Spring Спецификация разработки и API
- libs: Spring jar и пакет исходного кода
- схема: ограничения для файлов конфигурации Spring
Инверсия управления (IOC)
Инверсия управления (Inversion of Control) относится к праву на создание объектов, обращенных (к) Spring.
Чтобы использовать IOC, вам нужно импортировать пакеты, относящиеся к IOC, то есть несколько пакетов в контейнере core на рисунке выше: bean-компоненты, context, core и выражение четыре пакета.
Базовые концепты
В Java-разработке Ioc означает передачу созданного вами объекта элементу управления контейнером, а не традиционному прямому управлению внутри вашего объекта.
В традиционном программировании на Java SE мы создаем объекты непосредственно внутри объекта через new, а программа активно создает зависимые объекты, тогда как IoC имеет выделенный контейнер для создания этих объектов, то есть Ioc-контейнер управляет созданием объектов.
В традиционных приложениях мы активно контролируем объект, чтобы напрямую получать зависимые объекты, то есть вращение вперед; в то время как обратное вращение помогает контейнеру создавать и внедрять зависимые объекты; зачем реверсировать? Поскольку контейнер помогает нам находить и внедрять зависимые объекты, объект только пассивно принимает зависимые объекты, поэтому он инвертируется; какие аспекты реверсируются? Приобретение зависимых объектов отменяется.
Принцип реализации
Создайте объект традиционным способом:
UserDAO userDAO=new UserDAO();
Далее возможно интерфейсно-ориентированное программирование, полиморфизм:
UserDAO userDAO=new UserDAOImpl();
Недостаток этого метода в том, что интерфейс и класс реализации сильно связаны, и при переключении базового класса реализации необходимо модифицировать исходный код. Дизайн программы должен удовлетворять требованиям предка OCP, и программа должна быть расширена на основе максимально возможного отказа от изменения исходного кода программы. На этом этапе можно использовать заводской шаблон:
class BeanFactory{
public static UserDAO getUserDAO(){
return new UserDAOImpl();
}
}
Таким образом, несмотря на отсутствие связи между интерфейсом и классом реализации, связь между интерфейсом и фабрикой существует.
Используйте фабрику + отражение + файл конфигурации для достижения развязки,Это также базовая реализация Spring Framework IOC.
//xml配置文件
//<bean id="userDAO" class="xxx.UserDAOImpl"></bean>
class BeanFactory{
public static Object getBean(String id){
//解析XML
//反射
Class clazz=Class.forName();
return clazz.newInstance();
}
}
XML-разработка МОК
Включите файл xsd-configuration.hmtl в файл документации. Он определяет схему компонентов.
<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
<bean id="userService" class="x.y.UserServiceImpl">
</bean>
</beans>
вызывающий класс:
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)applicationContext.getBean("userService");
userService.save();
IOC и DI
DI относится к внедрению зависимостей.Предпосылка заключается в том, что должна быть среда IOC.Когда Spring управляет этим классом, он внедряет в него зависимости класса.
Например, в UserServiceImpl.java:
public class UserServiceImpl implements UserService{
private String name;
public void setName(String name){
this.name=name;
}
public void save(){
System.out.println("save "+name);
}
}
В файле конфигурации:
<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="userService" class="spring.demo1.UserServiceImpl">
<!--配置依赖的属性-->
<property name="name" value="tony"/>
</bean>
</beans>
Тестовый код:
@Test
public void demo2(){
//创建Spring工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)applicationContext.getBean("userService");
userService.save();
}
результат операции:
save tony
Видно, что свойства, настроенные в файле конфигурации, успешно установлены, когда Spring управляет классом. Если вы не используете внедрение зависимостей, вы не можете использовать интерфейс, вы можете использовать только класс реализации, чтобы установить его, потому что свойство не существует в интерфейсе.
Фабричный класс Spring
- BeanFactory: старая версия фабричного класса при вызове
getBean()
метод, создается экземпляр класса. - ApplicationContext: при загрузке файла конфигурации создаются экземпляры всех классов, управляемых Spring. Есть два класса реализации:
- Загрузка файлов конфигурации Classpath: ClassPathXMLApplicationContext
- ФайловыйИстемXMLApplicationContext: Загрузить файл конфигурации с диска
конфигурация bean-тега
- id: уникальное ограничение, никакие специальные символы не могут отображаться
- name: Теоретически можно повторить, но лучше не использовать в разработке. могут появляться специальные символы
жизненный цикл:
- init-method: метод для выполнения при инициализации bean-компонента.
- Уничтожение-метод: метод выполнения, когда боб разрушен
Диапазон:
- Сфера применения: Сфера действия bean-компонента бывает следующих типов, чаще всего используются первые два.
- singleton: по умолчанию создается с использованием одноэлементного режима.
- прототип: несколько экземпляров
- запрос: в веб-проекте после того, как Spring создает класс, он сохраняет его в области запроса
- сеанс: в веб-проекте после того, как Spring создает класс, он сохраняет его в области сеанса.
- globalsession: в веб-проектах должен использоваться в среде портлета
Настройки вставки свойств
- Свойства Конструктор Инъекционный режим: Класс автомобиля имеет два атрибута в процессе конфигурации, а именно имя и цену.
<bean id="car" class="demo.Car">
<constructor-arg name="name" value="bmw">
<constructor-arg name="price" value="123">
</bean>
- установка свойства метода: Класс Employee имеет два метода set, которые соответственно устанавливают имя обычного типа и Car ссылочного типа (используя ref для указания на идентификатор или имя ссылочного типа).
<bean id="employee" class="demo.Employee">
<property name="name" value="xiaoming">
<property name="car" ref="car">
</bean>
- Внедрение свойства для пространства имен P: Сначала вам нужно импортировать пространство имен p:
<beans xmlns="http://www.springframework.org/schema/beans"
//引入p名称空间
xmlns:p="http://www.springframework.org/schema/p"
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>
Если это обычное свойство:
<bean id="car" class="demo.Car" p:name="bmv" p:price="123">
</bean>
Если это ссылочный тип:
<bean id="employee" class="demo.Employee" p:name="xiaoming" p:car-ref:"car">
</bean>
- Внедрение свойств SpEL (Spring Expression Language) (Spring 3.x и выше)
<bean id="car" class="demo.Car">
<property name="name" value="#{'xiaoming'}">
<property name="car" ref="#{car}">
</bean>
- Набор атрибутов типа впрыска:
<bean id="car" class="demo.Car">
<property name="namelist">
<list>
<value>qirui</value>
<value>baoma</value>
<value>benchi</value>
</list>
</property>
</bean>
Многомодульная конфигурация разработки
- При загрузке файла конфигурации загружать несколько файлов конфигурации
- Внесите несколько файлов конфигурации в один файл конфигурации, реализуя
Разработка аннотации МОК
Пример
- Импортируйте пакет jar: В дополнение к четырем пакетам, упомянутым выше, также необходимо импортировать пакет aop.
- Создайте ApplicationContext.xml, используйте аннотации для введения ограничений контекста (XSD-Configuration.html).
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
</beans>
- Компонентное сканирование: Для разработки с использованием аннотаций IOC необходимо настроить сканирование компонентов, то есть какие классы в пакете используют аннотации IOC.
<context:component-scan base-package="demo1">
-
Добавляйте аннотации к классам
-
Используйте аннотации для установки значения свойства
Если у свойства есть метод set, добавьте аннотацию внедрения свойства к методу set.
Свойства не имеют заданных методов, добавьте аннотации к свойствам.
@Component("UserDao")//相当于配置了一个<bean> 其id为UserDao,对应的类为该类
public class UserDAOImpl implements UserDAO {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("save");
}
}
Примечание
1.@Component
Компонентные аннотации, используемые для изменения класса, руками этого класса для управления пружиной.
Есть три производных аннотации, которые работают одинаково и также используются для оформления классов.
- @Controller: украсьте класс веб-слоя
- @Service: украсьте класс сервисного слоя
- @Repository: украсьте класс слоя дао
2. Внедрение свойств
- Обычные свойства используют @Value для установки значения свойства.
- Свойства объекта используют @Autowired , который аннотируется по типу для внедрения свойства. Если вы хотите внедрить свойства по имени или идентификатору компонента, вам нужно использовать вместе @Autowired и @Qualifier.
- В реальной разработке используйте @Resource(name=" ") для завершения внедрения свойств в соответствии с именем объекта.
3. Другие примечания
- @PostConstruct эквивалентно init-методу, аннотации для функции инициализации
- @PreDestroy эквивалентен методу destroy, который используется для уничтожения аннотаций функций.
- @Scope Сфера аннотаций, единый общий вариант по умолчанию, существует много случаев @scope ("прототип")
Сравнение разработки XML и аннотаций для IOC
- Применимые сценарии: XML подходит для любого сценария, аннотации подходят только для классов, написанных вами, а классы, предоставленные не вами, не могут добавлять аннотации.
- Вы можете использовать XML для управления bean-компонентами и использовать аннотации для внедрения атрибутов.
Сравнение IOC и традиционных методов
- Как получить объект: Традиционно объект активно создается с помощью ключевого слова new. В методе IOC жизненный цикл объекта передается в управление Spring, а объект получается непосредственно из Spring. Также известна как инверсия управления — передача управления от себя к Spring.
разработка АОП
АОП — это аббревиатура Аспектно-ориентированного программирования, что означает аспектно-ориентированное программирование, технологию, которая обеспечивает унифицированное обслуживание программных функций посредством предварительной компиляции и динамических агентов времени выполнения и является продолжением ООП.
АОП может улучшить программу и может выполнять проверку разрешений, ведение журнала, мониторинг производительности, управление транзакциями и т. д. без изменения исходного кода.
То есть функции - это две категории, одна является основной бизнес-функцией, и одно вторичное улучшение. Два типа функций разрабатываются независимо друг от друга. Например, функция входа в систему является основной бизнес-функцией. Функция журнала - это вспомогательное улучшение. При необходимости журнал и логин компилируется вместе. Вспомогательная функция называется резкой, которая является селективной, идеей программирования с низким содержанием связи, которая сочетает в себе вырезанные поверхности и основные бизнес-функции, называются нарезанным программированием поверхности.
Первоначальный замысел АОП
СУХОЙ: не повторяйся SoC: разделение интересов
- Горизонтальное разделение: уровень представления -> уровень обслуживания -> уровень сохранения
- Вертикальное разделение: модульное разделение
- Разделение аспектов: разделение функциональных и нефункциональных требований
Зачем использовать АОП
- Сосредоточьтесь на одной проблеме/сквозной логике
- Легко добавлять/удалять проблемы
- Менее навязчивый, повышает читабельность кода и удобство сопровождения
В основном используется для контроля разрешений, управления кешем, управления транзакциями, журнала аудита, мониторинга производительности, распределенной трассировки, обработки исключений и т. д.
низкоуровневая реализация
Динамические прокси JDK могут генерировать прокси только для классов, реализующих интерфейсы. Динамический прокси Cglib может генерировать прокси-объекты для классов, которые не реализуют интерфейсы, и генерировать объекты подклассов.
Динамический прокси JDK
Динамический прокси JDK основан на реализации интерфейса, а нижний уровень основан на отражении.
public interface Subject {
public void request();
}
Класс реализации:
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("real subject request");
}
}
JDK-прокси:
public class JdkProxySubject implements InvocationHandler {
private RealSubject realSubject;
public JdkProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = null;
try {
result = method.invoke(realSubject, args);
} catch (Exception e) {
throw e;
} finally {
System.out.println("after");
}
return result;
}
}
тестовый класс
public class Client {
public static void main(String[] args) {
RealSubject rs=new RealSubject();
InvocationHandler handler=new JdkProxySubject(rs);
Subject subject=(Subject) Proxy.newProxyInstance(rs.getClass().getClassLoader(),rs.getClass().getInterfaces(),handler);
subject.request();
}
}
результат операции:
before
real subject request
after
В клиенте, позвонивProxy.newProxyInstance()
Создайте прокси-объект, где параметрами являются classLoader, интерфейс для проксирования и InvocationHandler прокси-объекта. при звонкеsubject.request()
Когда фактическим вызовом является метод вызова в JdkProxySubject.
Cglib
Cglib — это сторонняя библиотека классов для генерации кода с открытым исходным кодом, которая может динамически добавлять атрибуты и методы класса.
Прокси-серверы JDK реализованы на основе интерфейсов, тогда как Cglib основан на наследовании:
public class Hello {
public void hello(String str){
System.out.println("hello "+str);
}
}
Этот класс не реализует никакого интерфейса. Реализация через прокси CGLIB выглядит следующим образом: Сначала реализуйте MethodInterceptor, и вызов метода будет переадресован методу intercept() класса. Затем, когда вам нужно использовать класс, получите прокси-объект через динамический прокси CGLIB.
class MyMethodInterceptor implements MethodInterceptor{
...
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
logger.info("You said: " + Arrays.toString(args));
return proxy.invokeSuper(obj, args);
}
}
public class Test {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloConcrete.class);
enhancer.setCallback(new MyMethodInterceptor());
HelloConcrete hello = (HelloConcrete)enhancer.create();
System.out.println(hello.sayHello("I love you!"));
}
}
от CGLIBEnhancer
Чтобы указать целевой объект для проксирования, объект, который фактически обрабатывает логику прокси, и, наконец, вызовомcreate()
Метод получает прокси-объект, и вызовы всех неконечных методов этого объекта перенаправляются наMethodInterceptor.intercept()
метод.
Сравните два
Когда использовать JDK или CGLiB?
- Если целевой объект реализует интерфейс, по умолчанию будет использоваться реализация AOP динамического прокси-сервера JDK.
- Если целевой объект реализует интерфейс, вы можете заставить АОП реализовать CGLIB.
- Если целевой объект не реализует интерфейс, необходимо использовать библиотеку CGLIB, и Spring автоматически преобразует динамический прокси-сервер JDK в CGLIB.
Как Spring выбирает использование JDK или CGLiB?
- Когда компонент реализует интерфейс, Spring использует динамический прокси JDK.
- Когда bean-компонент не реализует интерфейс, Spring использует CGlib для его реализации.
- Вы можете принудительно использовать CGlib (добавьте
в конфигурацию spring).
АОП-разработка с помощью Spring (способ AspectJ XML)
AspectJ — это среда АОП, Spring представляет AspectJ и разрабатывает АОП на основе AspectJ.
связанные термины
- Точка соединения: точка соединения, точка, которую можно перехватить. Относится к точке, в которой разрешено вставлять аспект во время выполнения программы, который может быть функцией, путем к пакету, классом или выброшенным исключением.
- Pointcut: Pointcut, используемый для указания диапазона точек соединения, точки, которая действительно перехватывается, то есть метод, который действительно усиливается.
- Совет: Совет, который определяет работу аспекта возле точки, то есть, когда что-то делать. Например, до, после и т. д.
- Аспект: Аспект, совокупность подсказок и советов, как правило, представляет собой класс, абстрагированный от общей логики нескольких категорий. Класс Аспекта будет определять, когда, где и что делать.
- Введение: введение, улучшения на уровне класса.
- Цель: цель, улучшенный объект (класс), вплетенный в объект, подлежащий разрезанию.
- Плетение: Плетение — это процесс применения аспекта к точке соединения, соответствующей точечному разрезу. Аспекты вплетаются в целевой объект в указанных точках соединения.
- Прокси: прокси-объект, расширенный объект.
инструкции
- Импорт связанных пакетов
- импортировать файл конфигурации
<?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 http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->
</beans>
- Напишите целевой класс и настройте:
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("save");
}
@Override
public void update() {
System.out.println("update");
}
@Override
public void find() {
System.out.println("find");
}
@Override
public void delete() {
System.out.println("delete");
}
}
<bean id="productDao" class="demo1.ProductDaoImpl"></bean>
- Напишите класс аспектов, предполагая, что он используется для проверки авторизации и конфигурации
public class MyAspectXML {
public void checkPri(){
System.out.println("check auth");
}
}
<bean id="myAspect" class="demo1.MyAspectXML"></bean>
- Завершите усовершенствование целевого класса с помощью конфигурации AOP.
<aop:config>
<aop:pointcut expression="execution(* demo1.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:aspect ref="myAspect">
<aop:before method="chechPri" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
Тип уведомления
- Предварительное уведомление: перед выполнением целевого метода можно получить информацию о точечном сокращении.
<aop:before method="chechPri" pointcut-ref="pointcut1"/>
public void checkPri(JoinPoint joinPoint){
System.out.println("check auth "+joinPoint);
}
- Опубликовать уведомление: после выполнения целевого метода можно получить возвращаемое значение метода.
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
public void writeLog(Object result){
System.out.println("writeLog "+result);
}
- Совет по окружению: работайте до и после выполнения целевого метода, что может помешать выполнению целевого метода.
<aop:around method="around" pointcut-ref="pointcut3"/>
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("before");
Object result=joinPoint.proceed();
System.out.println("after");
return result;
}
- Уведомление об исключении: действие при возникновении исключения в программе.
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
public void afterThrowing(Throwable ex){
System.out.println("exception "+ex.getMessage());
}
- Последнее уведомление: эквивалент блока, независимо от того, есть ли код исключения, который будет выполняться
<aop:after method="finallyFunc" pointcut-ref="pointcut4"/>
public void finallyFunc(){
System.out.println("finally");
}
- Уведомление о реферале: обычно не используется
Выражения Spring Pointcut
Завершено на основе исполнительной функции
Синтаксис: [модификатор доступа] возвращаемое значение метода имя пакета имя класса имя метода (параметр)
Где любое поле может использовать * вместо любого значения
АОП Spring разработан на основе аннотаций AspectJ.
Шаги развития
- импортный пакет jar
- Установите файл конфигурации:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>
- Напишите целевой класс конфигурации
<bean id="orderDao" class="demo1.OrderDao"></bean>
public class OrderDao {
public void save(){
System.out.println("save order");
}
public void update(){
System.out.println("update order");
}
public void delete(){
System.out.println("delete order");
}
public void find(){
System.out.println("find order");
}
}
- Включить автоматический прокси-сервер аннотации aop
<aop:aspectj-autoproxy/>
- Напишите класс аспекта и настройте его
@Aspect
public class MyAspectAnno {
@Before(value="execution(* demo1.OrderDao.save(..))")
public void before(){
System.out.println("before");
}
}
<bean id="myAspect" class="demo1.MyAspectAnno">
Тип аннотации
Аннотации в основном делятся на три категории:
- @Aspect: указывает, что это класс аспекта.
- @Pointcut: указывает pointcut, то есть класс или метод, который необходимо улучшить.
Эта аннотация должна быть составлена с помощью аспектных выражений. Выражения аспекта состоят из трех частей: обозначений, подстановочных знаков и операторов.
Индикаторы делятся на:
- Метод сопоставления: исполнение()
execution(
[modifier-pattern]// 修饰符
ret-type-pattern//返回类型
[declaring-type-pattern]//包名
name-pattern(param-pattern)//方法名
[throws-pattern]//抛出异常声明
)
- Соответствующие аннотации: @target(), @args(), @within(), @annotation()
- Соответствующие пакеты/классы: внутри()
@Pointcut("within(demo.service.*)")
public void pointcut(){}
- Соответствующие объекты: this(), bean(), target()
- Соответствующие аргументы: args()
//匹配任何只有一个Long参数的方法
@Pointcut("args(Long)")
//匹配第一个参数为Long的方法
@Pointcut("args(Long,..)")
Подстановочные знаки:
-
- соответствует любому количеству символов
-
- соответствует указанному классу и его подстолбцам
- .. для произвольного количества подпунктов соответствующий параметр или
Основными операторами являются &&, ||, ! То есть и или не три.
- Совет: когда выполнять расширенный метод
- @Before: до уведомления
- @AfterReturning: опубликовать уведомление
@AfterReturning(value="execution(* demo1.OrderDao.save(..))",returning="result")
public void after(Object result){
System.out.println("after "+result);
}
- @Around: объемные уведомления
@Around(value="execution(* demo1.OrderDao.save(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("before");
Object obj=joinPoint.proceed();
System.out.println("after");
return obj;
}
- @AfterThrowing: выдает исключение
@AfterThrowing(value="execution(* demo1.OrderDao.save(..))",throwing="e")
public void afterThrowing(Throwable e){
System.out.println("exception:"+e.getMessage();
}
- @After: окончательное уведомление
@After(value="execution(* demo1.OrderDao.save(..))")
public void after(){
System.out.println("finally");
}
- @PointCut: аннотация pointcut
@PointCut(value="execution(* demo1.OrderDao.save(..))")
private void pointcut1(){}
Преимущество аннотаций заключается в том, что вам нужно только поддерживать точку, вместо того, чтобы изменять каждую аннотацию при ее изменении.
Шаблон Spring JDBC
Spring также предоставляет решения для уровня сохраняемости, а именно модули ORM и шаблоны JDBC. Для JDBC в качестве класса шаблона предоставляется org.springframework.jdbc.core.JdbcTemplate.
Использование шаблонов JDBC
- Расскажите о пакетах jar, драйверах баз данных и связанных с jdbc пакетах Spring.
- Основное использование:
public void demo1(){
//创建连接池
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring4");
dataSource.setUsername("root");
dataSource.setPassword("123456");
//创建JDBC模板
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
jdbcTemplate.update("insert into account values (null,?,?)", "xiaoming",1000d);
}
- Передайте пул соединений и шаблоны управлению Spring
- Конфигурационный файл:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource;">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///spring4"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate;">
<property name="dataSource" ref="dataSource"></property>
</bean>
- Тестовый файл:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcDemo2 {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
public void demo2(){
jdbcTemplate.update("insert into account values (null,?,?)", "xiaolan",1000d);
}
}
Использование пула соединений с базой данных с открытым исходным кодом
- Конфигурация с использованием DBCP:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://192.168.66.128/spring4"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
- Конфигурация с использованием C3P0:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://192.168.66.128/spring4"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
- импортировать файл внешних свойств
Во-первых, внешний файл свойств:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.66.128/spring4
jdbc.username=root
jdbc.password=123456
Затем настройте файл свойств:
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
CRUD-операции
Операторы вставки, обновления и удаления работают с методом обновления шаблона.
public void demo(){
jdbcTemplate.update("insert into account values (null,?,?)", "xiaoda",1000d);
jdbcTemplate.update("update account set name=?,money=? where id=?", "xiaoda",1000d,2);
jdbcTemplate.update("delete from account where id=?", 6);
}
Операция запроса:
public void demo3(){
String name=jdbcTemplate.queryForObject("select name from account where id=?",String.class,5);
long count=jdbcTemplate.queryForObject("select count(*) from account",Long.class);
}
Инкапсулируйте возвращенный результат в класс:
public void demo4(){
Account account=jdbcTemplate.queryForObject("select * from account where id=?", new MyRowMapper(),5);
}
в:
class MyRowMapper implements RowMapper<Account>{
@Override
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account=new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
return account;
}
}
Весеннее управление транзакциями
дела
Транзакция — это логическая группа операций, и единицы, составляющие эту группу операций, либо завершаются успешно, либо завершаются неудачно.
Имеет четыре свойства:
- Атомарность: транзакции неделимы
- Согласованность: целостность данных остается последовательной до и после выполнения транзакций
- Изоляция: осуществление транзакции не должно мешать другим делам.
- Долговечность: после завершения транзакции данные сохраняются в базе данных.
Если не учитывать изоляцию, это может привести к проблемам с безопасностью:
- Прочитайте вопрос:
- Грязное чтение: одна транзакция считывает незафиксированные данные из другой транзакции.
- Неповторяющееся чтение: одна транзакция считывает данные обновления, отправленные другой транзакцией, что приводит к несогласованным результатам нескольких запросов в одной транзакции.
- Phantom read: данные транзакции вставки.
- Напиши вопрос:
- потерянное обновление
Решить проблему чтения: установить уровень изоляции транзакций
- Чтение незафиксированного: Незафиксированное чтение, невозможно решить какие-либо проблемы с чтением
- Чтение зафиксировано: Чтение было зафиксировано для решения проблемы грязного чтения.
- Повторяемое чтение: Повторяемое чтение, решение проблемы грязного чтения и неповторяемого чтения.
- Сериализуемый: сериализовать, решить все проблемы с чтением
API управления транзакциями
- PlatformTransactionManager: менеджер транзакций платформы
Это интерфейс с несколькими различными классами реализации, например, нижний уровень DataSourceTransactionManager использует JDBC для управления транзакциями, а нижний уровень HibernateTransactionManager использует Hibernate для управления транзакциями.
- TransactionDefinition: информация об определении транзакции
Сопутствующая информация, используемая для определения транзакций, например уровень изоляции, информация о времени ожидания, поведение распространения, доступ только для чтения и т. д.
- TransactionStatus: статус транзакции.
Объект, используемый для записи состояния транзакции во время управления транзакциями.
Связь вышеуказанного API: Когда Spring осуществляет управление транзакциями, сначалаМенеджер транзакций платформыв соответствии сИнформация о определении транзакцииВыполнять управление транзакциями, в процессе управления транзакциями генерируются различные состояния, и информация об этих состояниях записывается встатус транзакциисреди объектов.
Поведение распространения транзакции
Распространение транзакций в основном решает проблему взаимного вызова методов бизнес-уровня (службы), то есть как действовать, когда разные транзакции существуют в разных бизнесах.
Spring обеспечивает распространение семи материй, разделенных на три категории:
- Гарантия нескольких операций в одной транзакции
- PROPAGATION_REQUIRED: метод B вызывает метод A. Если есть транзакция в A, используйте транзакцию в A и включите операции в B в транзакцию, в противном случае создайте новую транзакцию и включите операции в A и B. (дефолт)
- PROPAGATION_SUPPORTS: если есть транзакция в A, используйте транзакцию A; в противном случае не используйте транзакцию
- Пропагандирование_mandatory: если a имеет транзакцию, используйте транзакцию A; в противном случае брось исключение
- Гарантирует, что несколько операций не находятся в одной транзакции
- PROPAGATION_REQUIRES_NEW: Если в A есть транзакция, приостановить ее, создать новую транзакцию и содержать только свои собственные операции. В противном случае создается новая транзакция, содержащая только собственные операции.
- PROPAGATION_NOT_SUPPORTED: если в A есть транзакция, приостановить и не использовать транзакцию.
- PROPAGATION_NEVER: если в A есть транзакция, генерируется исключение, то есть его нельзя запустить с транзакцией.
- вложенные транзакции
- PROPAGATION_NESTED: Если A имеет транзакцию, выполнить в соответствии с транзакцией A. После завершения выполнения установите SavePoint, а затем выполните операцию B. Если возникает исключение, вы можете откатиться в исходное состояние или состояние SavePoint.
пример
Взяв в качестве примера передачу, класс уровня DAO бизнес-уровня выглядит следующим образом:
public interface AccountDao {
public void outMoney(String from,Double money);
public void inMoney(String to,Double money);
}
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
@Override
public void outMoney(String from, Double money) {
this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money,from);
}
@Override
public void inMoney(String to, Double money) {
this.getJdbcTemplate().update("update account set money = money + ? where name = ?",money,to);
}
}
public interface AccountService {
public void transfer(String from,String to,Double money);
}
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String from, String to, Double money) {
accountDao.outMoney(from, money);
accountDao.inMoney(to, money);
}
}
Настройте класс в XML:
<bean id="accountService" class="tx.demo.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="accountDao" class="tx.demo.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
Организатор 1: программное управление транзакциями
- Настройка диспетчера транзакций платформы
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
- Настройка классов шаблонов управления транзакциями
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
- Внедрение шаблонов управления транзакциями на бизнес-уровне
<bean id="accountService" class="tx.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
- Кодирование для управления транзакциями
//ServiceImpl类中:
private TransactionTemplate transactionTemplate;
@Override
public void transfer(String from, String to, Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
accountDao.outMoney(from, money);
accountDao.inMoney(to, money);
}
});
}
Декларативное управление транзакциями (конфигурации, на основе мысли AOP)
- Декларативное управление транзакциями в XML
- Настройка диспетчера транзакций
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
- Настройка уведомлений о транзакциях
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
- Настройка транзакций AOP
<aop:config>
<aop:pointcut expression="execution(* tx.demo2.AccountServiceImpl.*(..))" id="pointcut1"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>
- Метод аннотации
- Настройте диспетчер транзакций в соответствии с приведенным выше
- Аннотация для включения управления транзакциями:
<tx:annotation-driven transaction-manager="transactionManager"/>
- Добавьте аннотацию @Transactional к классам, использующим транзакции.