1.AOP
1.1 what is AOP
In the software industry, AOP is the abbreviation of Aspect Oriented Programming, which means: Aspect Oriented Programming through precompiler
Dynamic agent is a technology to realize the unified maintenance of program functions. AOP is the continuation of OOP, a hot spot in software development, an important content in Spring framework, and a derivative paradigm of functional programming. AOP can isolate each part of business logic, reduce the coupling between each part of business logic, improve the reusability of program, and improve the efficiency of development.
To understand aspect programming, you need to understand what aspect is first. Divide a watermelon into two parts with a knife, and the cut is the cut surface; For cooking, the pot and stove work together to complete cooking. The pot and stove are cut noodles. In web hierarchy design, web layer - > gateway layer - > service layer - > data layer, and each layer is also an aspect. In programming, there are aspects between objects, methods, and modules.
When we do activities, we usually check the effectiveness of each interface (start, end, etc.) and whether the interface requires user login.
According to normal logic, we can do this.
The problem is that the number of interfaces requires code copies. For a "lazy man", this is intolerable. OK, propose a public method, and each interface calls this interface. There's a bit of slicing here.
There is also a problem. Although I don't have to copy the code every time, each interface must call this method. So there is the concept of facet. I inject the method into a certain place (tangent point) of the interface call.
There is also a problem. Although I don't have to copy the code every time, each interface must call this method. So there is the concept of facet. I inject the method into a certain place (tangent point) of the interface call.
In this way, the interface only needs to care about the specific business, and does not need to pay attention to other logic or processing not concerned by the interface.
In the red box, it is aspect oriented programming.
1.2 what can AOP do
1. It is to help us reduce the writing of repeated code, so as to improve readability and development efficiency
2. Enhance the program without modifying the source code
3.AOP can perform permission verification, logging, performance monitoring and transaction control
1.3 bottom layer implementation
AOP depends on IOC. In AOP, a proxy class is used to wrap the target class, intercept the method execution of the target class in the proxy class, and weave auxiliary functions. When the Spring container is started, a proxy class bean is created to replace the target class and register it in the IOC, so that the target class instance injected into the application code is actually an instance of the proxy class corresponding to the target class, that is, the proxy class generated by the target class is processed using AOP.
Agency mechanism:
The underlying layer of Spring's AOP uses two proxy mechanisms:
JDK dynamic proxy: generate proxy for classes that implement interfaces
Cglib's dynamic proxy: generate proxy for classes that do not implement interfaces The underlying bytecode enhancement technology is applied to generate subclass objects of the current class
1.4 AOP related terms
- Joinpoint: the so-called connection point refers to those intercepted points. In spring, these points refer to methods because
spring only supports method type join points
- Advice: the so-called notification means that what needs to be done after intercepting the Joinpoint is notification The notice is divided into pre notice and pre notice
Notification, post notification, exception notification, final notification, surround notification (functions to be completed in all aspects)
- Pointcut: the so-called pointcut refers to the definition of which joinpoints we want to intercept
- Introduction: introduction is a special notice. Without modifying the class code, introduction can be run in
Expect to dynamically add some methods or Field for the class
- Target: the target object of the proxy
- Weaving: refers to the process of applying enhancements to the target object to create a new proxy object. spring uses dynamic proxy
While AspectJ adopts compile time weaving and class loading in time weaving
- Proxy: after a class is enhanced by AOP weaving, a resulting proxy class is generated
- Aspect: a combination of pointcuts and notifications (Introductions)
1.5 how to use AOP
1. Dynamic agent
package com.tledu.dao.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DynamicProxy implements InvocationHandler { private Object obj; public DynamicProxy(Object obj){ this.obj = obj; } /** * @param proxy Proxy object * @param method Proxy method * @param args Method parameters * @return Method * @throws Throwable abnormal */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Pre operation before(method); method.invoke(obj,args); //Post operation after(method); return null; } private void before(Method method) { System.out.println(method.getName()+" Start call"); } private void after(Method method) { System.out.println(method.getName()+" End of call"); } }
test
public static void main(String[] args) { UserDaoImpl userDao = new UserDaoImpl(); /** The first parameter: the class parser of the real object The second parameter: the implemented interface array The third parameter: when the proxy method is called, the method will be assigned to this parameter */ IUserDao iu = (IUserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(),new DynamicProxy(userDao)); User u = new User(); u.setId(3); u.setName("aaa"); iu.add(u); }
newProxyInstance, the method has three parameters:
Loader: which class loader is used to load the proxy object
interfaces: the interface that the dynamic proxy class needs to implement
InvocationHandler: create a proxy by passing in the object to be proxy. When the dynamic proxy method is executed, it will call the invoke method in the create proxy class to execute
be careful:
The principle of JDK dynamic proxy is to create a new class with the incoming interface according to the defined rules. This is why when using dynamic proxy, you can only use the interface reference to point to the proxy, but not the incoming class reference to execute the dynamic class.
2. Annotation method
It's OK to introduce three again before IOC, because Spring's AOP is developed based on AspectJ
Introducing AOP constraints in configuration files
<?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-2.5.xsd"> <!-- introduce AOP constraint --> <!-- Use annotation method --> <context:annotation-config /> <context:component-scan base-package="com.tledu" /> <!-- open AOP Annotation method of --> <aop:aspectj-autoproxy /> </beans>
Enable facet support @ EnableAspectJAutoProxy by annotation
AOP class
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component @Aspect public class LogInterceptor { @Pointcut("execution(public * com.tledu.service..*.add(..))") public void myMethod() { // Suppose this method is the proxy method } @Before("myMethod()") public void beforeMethod() { System.out.println(" execute start"); } @After("myMethod()") public void afterMethod() { System.out.println(" execute end"); } // Surround, both Before and After, is equivalent to @ Before and @ After being used together @Around("myMethod()") public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable { // @Around can also be used with @ Before and @ After System.out.println("around start"); // Call the proxied method pjp.proceed(); System.out.println("around end"); } }
3. XML mode
Import jar package
It is introduced in the same way as annotation
<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-2.5.xsd"> <context:annotation-config/> <context:component-scan base-package="com.tledu"/> <!--open AOP annotation--> <!--<aop:aspectj-autoproxy />--> <bean id="logInterceptor" class="com.tledu.aop.LogInterceptor"></bean> <aop:config> <aop:aspect id="logAspet" ref="logInterceptor"> <!-- Method of proxy required --> <aop:pointcut expression="execution(public * com.tledu.service..*.add(..))" id="pointcut" /> <!-- Before and after execution --> <aop:before method="beforeMethod" pointcut-ref="pointcut" /> <!-- Or write it like this,So there's no need pointcut Label --> <!-- <aop:before method="before" pointcut="execution(public * com.tledu.service..*.add(..))" /> --> <aop:after method="afterMethod" pointcut-ref="pointcut" /> <!-- surround,Generally either use around To and use before and after Will not be used together --> <aop:around method="aroundMethod" pointcut-ref="pointcut" /> </aop:aspect> </aop:config> </beans>
AOP class
Same as the annotation, but remove the annotation
import org.aspectj.lang.ProceedingJoinPoint; public class LogInterceptor { public void myMethod() { // Suppose this method is the proxy method } public void before() { System.out.println(" execute start"); } public void after() { System.out.println(" execute end"); } // Surround, both Before and After, is equivalent to @ Before and @ After being used together public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable { // @Around can also be used with @ Before and @ After System.out.println("around start"); // Call the proxied method pjp.proceed(); System.out.println("around end"); } }
Test class
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml"); UserService userService = context.getBean(UserService.class); User u = new User(); u.setName("Li Si"); userService.add(u); }
2. Use of JDBC template in spring
2.1 what is a jdbc Template
It is an object provided in the spring framework and a simple encapsulation of the original Jdbc API object. The spring framework provides us with many operation template classes.
Operation of relational data:
JdbcTemplate
HibernateTemplate
To operate nosql database:
RedisTemplate
Operation message queue:
JmsTemplate
Our protagonist today is spring JDBC In jar, in addition to importing the jar package, we also need to import a spring-tx.jar (which is transaction related)
2.2 creation of JDBC template object
We can refer to its source code to explore:
public JdbcTemplate() { } public JdbcTemplate(DataSource dataSource) { setDataSource(dataSource); afterPropertiesSet(); } public JdbcTemplate(DataSource dataSource, boolean lazyInit) { setDataSource(dataSource); setLazyInit(lazyInit); afterPropertiesSet(); }
In addition to the default constructor, you need to provide a data source. Since there is a set method, we can configure these objects in the configuration file according to the dependency injection we learned before
2.3 configuring data sources
1. Environmental construction
2. Configuration file import constraints
<?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>
3. Configure DBCP data source
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/ssm"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean>
The spring framework also provides a built-in data source. We can also use spring's built-in data source, which is located in spring JDBC Jar
<!-- Configure data sources--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/ssm"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean>
Dou E can choose one of the above two
2.4 addition, deletion, modification and query
1. Configure jdbc Template
<?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"> <!-- Configure a database operation template: JdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- Configure data sources --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/ssm"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> </beans>
2. Basic usage
public static void main(String[] args) { DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/ssm"); ds.setUsername("root"); ds.setPassword("root"); //1. Create a JdbcTemplate object JdbcTemplate jt = new JdbcTemplate(); //Set data source for jt jt.setDataSource(ds); //2. Perform the operation jt.execute("insert into t_user(username,password)values('ccc','aaa')"); }
3. Basic usage after spring integration
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); JdbcTemplate jt = (JdbcTemplate) context.getBean("jdbcTemplate"); //jdbcTemplate.execute("insert into t_user(username,password)values('zhang Meiling ',' 888 ')); // Query all List<User> accounts = jt.query("select * from t_user",new UserRowMapper()); for (User account : accounts) { System.out.println(account); } System.out.println("--------"); User user = jt.queryForObject("select * from t_user where id = ?",new BeanPropertyRowMapper<User>(User.class),1); System.out.println(user); System.out.println("--------"); //Return the total number of entries with id greater than 3 Integer count = jt.queryForObject("select count(*) from t_user where id > ?", Integer.class, 3); System.out.println(count); //Multi condition query, fuzzy query List<User> ulist = jt.query("select * from t_user where t_user.username like ? and nickname like ? ",new UserRowMapper(),new Object[]{"%a%","%a%"}); System.out.println(ulist.size()); for (User user1 : ulist) { System.out.println(user1); }
Define User's encapsulation policy
public class UserRowMapper implements RowMapper<User> { @Override public User mapRow(ResultSet rs, int i) throws SQLException { User u = new User(); u.setId(rs.getInt("id")); u.setUsername(rs.getString("username")); return u; } }
2.5 add jdbc Template to Dao layer
1. Entity class
public class User { private Integer id; private String username; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + '}'; } }
2. Define IUserDao interface
public interface IUserDao { //Add a user message void add(User user); //Delete a piece of data according to id void delete(Integer id); //Modify a piece of data void update(User user); //Query user information list according to criteria List<User> getUserList(User user); //Query a piece of data by id User getUserById(Integer id); //Get the total number of entries Integer getListCount(); }
3. Add JDBC template in UserDaoImpl implementation class
public class UserDaoImpl implements IUserDao { private JdbcTemplate jdbcTemplate; @Override public void add(User user) { String sql = " insert into t_user(username) values('"+user.getUsername()+"') "; jdbcTemplate.execute(sql); } @Override public void delete(Integer id) { String sql = "delete from t_user where id = "+id+""; jdbcTemplate.execute(sql); } @Override public void update(User user) { String sql = "update t_user set username = '"+user.getUsername()+"' where id = "+user.getId()+""; jdbcTemplate.execute(sql); } @Override public List<User> getUserList(User user) { String sql = " select * from t_user where 1=1 "; if(user.getUsername()!=null){ sql += "and username like '%"+user.getUsername()+"%'"; } return jdbcTemplate.query(sql,new UserRowMapper()); } @Override public User getUserById(Integer id) { String sql = " select * from t_user where id = "+id+" "; return jdbcTemplate.queryForObject(sql,new UserRowMapper()); } @Override public Integer getListCount() { String sql = "select count(*) from t_user where username like '%beautiful%'"; return jdbcTemplate.queryForObject(sql,Integer.class); } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } }
4. Inject JDBC template into UserDaoImpl in the configuration file
<?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"> <!-- Configure the persistence layer of the account --> <bean id="accountDao" class="com.tledu.dao.impl.UserDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!-- Configure a database operation template: JdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- Configure data sources --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/ssm"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> </beans>
5. Test
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); JdbcTemplate jt = (JdbcTemplate) context.getBean("jdbcTemplate"); //jdbcTemplate.execute("insert into t_user(username,password)values('zhang Meiling ',' 888 ')); // Query all List<User> accounts = jt.query("select * from t_user",new UserRowMapper()); for (User account : accounts) { System.out.println(account); } System.out.println("--------"); //Query a piece of data by id User user = jt.queryForObject("select * from t_user where id = ?",new BeanPropertyRowMapper<User>(User.class),1); System.out.println(user); System.out.println("--------"); //Return the total number of entries with id greater than 3 Integer count = jt.queryForObject("select count(*) from t_user where id > ?", Integer.class, 3); System.out.println(count); //Multi condition query, fuzzy query List<User> ulist = jt.query("select * from t_user where t_user.username like ? and nickname like ? ",new UserRowMapper(),new Object[]{"%a%","%a%"}); System.out.println(ulist.size()); for (User user1 : ulist) { System.out.println(user1); }
6. Problems
Is there any problem with this method?
answer:
There's a small problem. When we have many Daos, each dao has some repetitive code. Here is the duplicate code:
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
7. Inherit JdbcDaoSupport
JdbcDaoSupport is a class provided to us by the spring framework. A JdbcTemplate object is defined in this class, which can be obtained and used directly. However, to create this object, you need to provide it with a data source:
The specific source code is as follows:
public abstract class JdbcDaoSupport extends DaoSupport { //Define object private JdbcTemplate jdbcTemplate; //The set method injects the data source to determine whether it is injected. After injection, a JdbcTemplate is created public final void setDataSource(DataSource dataSource) { if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) { //If a data source is provided, create a JdbcTemplate this.jdbcTemplate = createJdbcTemplate(dataSource); initTemplateConfig(); } } //Create a JdcbTemplate using a data source protected JdbcTemplate createJdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } //Of course, we can also inject the JdbcTemplate object public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; initTemplateConfig(); } //Use the getJdbcTmeplate method to obtain the operation template object public final JdbcTemplate getJdbcTemplate() { return this.jdbcTemplate; }
8. UserDaoImpl implementation class inherits JdbcDaoSupport
public class UserDaoImpl2 extends JdbcDaoSupport implements IUserDao { //private JdbcTemplate jdbcTemplate; @Override public void add(User user) { String sql = " insert into t_user(username) values('"+user.getUsername()+"') "; super.getJdbcTemplate().execute(sql); } @Override public void delete(Integer id) { String sql = "delete from t_user where id = "+id+""; super.getJdbcTemplate().execute(sql); }
9. In ApplicationContext Inject dataSource into UserDaoImpl in XML
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/ssm"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="userDao" class="com.tledu.dao.impl.UserDaoImpl2"> <!--<property name="jdbcTemplate" ref="jdbcTemplate"></property>--> <property name="dataSource" ref="dataSource"></property> </bean>
10. Test
public class UserDaoImplTest2 { private ApplicationContext context; @Before public void before(){ context = new ClassPathXmlApplicationContext("applicationContext.xml"); } @Test public void add(){ IUserDao userDao = context.getBean(UserDaoImpl2.class); User user = new User(); user.setUsername("JoSon"); userDao.add(user); } @Test public void delete(){ IUserDao userDao = context.getBean(UserDaoImpl2.class); userDao.delete(26); }